﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Linq;
using UMC.Web;
using UMC.Net;
using System.Text.RegularExpressions;
using System.Text;
using System.Security.Cryptography;
using System.Collections.Specialized;
using System.IO.Compression;
using Microsoft.VisualBasic;
using System.Runtime.CompilerServices;
using UMC.Data;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;
using System.Buffers.Binary;
using UMC.SshNet.Security.Org.BouncyCastle.Utilities.Encoders;
using System.Diagnostics.SymbolStore;
using UMC.ITME.Entities;

namespace UMC.ITME
{

    public class HttpProxy
    {
        public HttpProxy(SiteConfig site, UMC.Net.NetContext context, int staticModel, StringValue pfxDomain)
        {
            this.Site = site;
            this.IsLog = site.Site.IsDebug == true;
            this.PfxDomain = pfxDomain;

            this.Context = context;
            this.User = context.Token.Identity();

            this.RawUrl = context.PathQuery;

            this.StaticModel = staticModel;


            if (site.Domains.Length > 0)
            {
                this.Domain = WeightUri(pfxDomain);
            }
            CheckRawUrl();

            if (context.Cookies.Count > 0)
            {
                if (Utility.TryParse(context.Cookies.Get(DeviceIndex.Span).Span, 10, out var deviceIndex) == false)
                {
                    deviceIndex = 0;
                }


                this.SiteCookie = DataFactory.Instance().Cookie(_RootKey, User.Id.Value, deviceIndex) ?? new Entities.Cookie { Domain = this._RootKey, user_id = context.Token.UserId.Value, IndexValue = 0 };

                this.cookieSet = new CookieSet(this.SiteCookie.CookieValue);
                InitClientCookie(pfxDomain);
                foreach (var k in this.Site.AppendCookies)
                {
                    if (k.Prefix.IsEmpty)
                    {
                        this.Cookies[k.Name] = k.Value;
                    }
                    else if (context.Host.Span.StartsWith(k.Prefix.Span) || k.Prefix.Span.SequenceEqual("*"u8))
                    {
                        var value = WebServlet.WebHeaderConfValue(k, context, String.Empty);
                        if (value.IsEmpty == false && context.Cookies.TryGet(k.Name.Span, out var _) == false)
                        {
                            this.Context.AddHeader(StringValue.SetCookie, $"{k.Name}={value}; Path=/");
                        }
                    }
                }



                if (site.Test.Length > 0 && User.IsAuthenticated)
                {
                    var authManager = UMC.Security.AuthManager.Instance();
                    for (var i = 0; i < site.Test.Length; i++)
                    {
                        var tUrl = site.Test[i];
                        if (tUrl.Users.Contains(User.Name))
                        {
                            this.Domain = new Uri(tUrl.Url);
                            break;
                        }
                        else if (tUrl.Auths.Length > 0)
                        {
                            if (authManager.Check(this.User, 0, tUrl.Auths).Any(r => r.Item1 == 1))
                            {
                                this.Domain = new Uri(tUrl.Url);
                                break;

                            }
                        }
                    }
                }

            }
            else
            {
                this.SiteCookie = new Entities.Cookie { Domain = this._RootKey, user_id = context.Token.UserId.Value, IndexValue = 0 };
                this.cookieSet = new CookieSet(Array.Empty<byte>());
                this.domainCookie = new CookieSet(Array.Empty<byte>());
            }
            context.OutputHeaded(this.SaveCookie);

        }
        private HttpProxy(HttpProxy proxy, SiteConfig siteConfig)
        {
            var user = siteConfig.Site.Account;

            this.Site = siteConfig;
            this.IsLog = proxy.IsLog;
            this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(siteConfig.Root, user));

            this.SiteCookie = new Entities.Cookie
            {
                Account = user,
                user_id = UMC.Data.Utility.Guid(user, true),
                Domain = this.Site.Root,
                IndexValue = 0
            };
            this.IsChangeUser = false;
            this.Context = proxy.Context;
            this.Domain = proxy.Domain;
            this.RawUrl = proxy.RawUrl;
            this.PfxDomain = proxy.PfxDomain;

            this.User = proxy.User;
            this._RootKey = proxy._RootKey;

            this.domainCookie = this.cookieSet = new CookieSet(Array.Empty<byte>());
        }
        public Uri Domain
        {
            get;
            private set;
        }
        public SiteConfig Site
        {
            get;
            private set;
        }
        public UMC.ITME.Entities.Cookie SiteCookie
        {
            get;
            private set;
        }

        public bool? IsChangeUser
        {
            get;
            set;
        }
        String sourceUP;
        public StringValue PfxDomain
        {
            get;
            private set;
        }

        public string Password
        {
            get;
            private set;
        }
        static StringValue DeviceIndex = new StringValue("DeviceIndex");


        public static int WeightUri(SiteConfig site, Net.NetContext context)
        {
            if (site.WeightTotal > 0)
            {
                var value = 0;
                if (site.WeightTotal > 1)
                {
                    switch (site.Site.SLB ?? 0)
                    {
                        default:
                        case 0:
                            value = Random.Shared.Next(0, site.WeightTotal);
                            break;
                        case 1:
                            value = Math.Abs(Utility.Random(context.UserHostAddress) % site.WeightTotal);
                            break;
                        case 2:
                            var cookie = context.Cookies.Get("device"u8);
                            if (cookie.IsEmpty)
                            {
                                cookie = context.Headers.Get("Cookie"u8);
                                if (cookie.IsEmpty == false)
                                {
                                    value = Math.Abs(Utility.Random(cookie) % site.WeightTotal);
                                }
                            }
                            else
                            {
                                value = Math.Abs(Utility.Random(cookie) % site.WeightTotal);
                            }
                            ;
                            break;
                    }
                }

                var qty = 0;
                for (var i = 0; i < site.Weights.Length; i++)
                {
                    qty += site.Weights[i];
                    if (value < qty)
                    {
                        return i;
                    }
                }
            }
            return 0;
        }
        Uri WeightUri(StringValue p)
        {
            Uri url;
            var d = this.Site.Domains[WeightUri(this.Site, this.Context)];
            var dIndex = d.IndexOf('*');
            if (dIndex > -1)
            {

                var host = d.Substring(dIndex + 1);

                if (p.IsEmpty)
                {
                    if (this.Site.AllowRootDomain || this.Site.IsForwardProxy)
                    {
                        _RootKey = this.Site.Root;

                        return new Uri($"{d.Substring(0, dIndex)}{host.Substring(1)}");

                    }
                    else
                    {
                        var home = this.Site.GetHome();//
                        if (home.StartsWith("http://") || home.StartsWith("https://"))
                        {
                            this.Context.Redirect(ReplaceRedirect(new StringValue(home)).Span.UTF8());
                        }
                        else
                        {
                            this.Context.Redirect(this.Context.Url.AbsoluteUri.Replace(this.Context.Url.Host, $"www-{this.Site.Root}{WebServlet.DomainUnion}{WebServlet.MainDomain}"));
                        }
                        throw new WebAbortException();
                    }
                }
                _RootKey = $"{this.Site.Root}_{p}";

                if (this.Site.ReferenceHost.TryGetValue(p, out url) == false)
                {

                    if (this.Site.PrefixHost.TryGetValue(p, out var pfx))
                    {
                        url = new Uri($"{d.Substring(0, dIndex)}{pfx}{host}");
                    }
                    else
                    {
                        url = new Uri($"{d.Substring(0, dIndex)}{p}{host}");
                    }
                }

            }
            else
            {
                _RootKey = this.Site.Root;
                url = new Uri(d);
            }
            return url;

        }

        UMC.Security.Identity _Account;
        public UMC.Security.Identity Account
        {
            get
            {
                if (_Account == null)
                {
                    var user = this.User;
                    if (String.IsNullOrEmpty(this.SiteCookie.Account))
                    {
                        _Account = UMC.Security.Identity.Create(user, UMC.Data.DataFactory.Instance().Roles(user.Id.Value, this.Site.Site.SiteKey.Value));

                    }
                    else if (String.Equals(this.SiteCookie.Account, user.Name))
                    {
                        var feildConfig = UMC.Data.JSON.Deserialize<Hashtable>(this.SiteCookie.Config);//?? new Hashtable();
                        if (feildConfig?.ContainsKey("__ROLE") == true)
                        {
                            _Account = UMC.Security.Identity.Create(user, (feildConfig["__ROLE"] as string ?? "").Split(','));
                        }
                        else
                        {
                            _Account = UMC.Security.Identity.Create(user, UMC.Data.DataFactory.Instance().Roles(user.Id.Value, this.Site.Site.SiteKey.Value));
                        }
                    }
                    else
                    {
                        var feildConfig = UMC.Data.JSON.Deserialize<Hashtable>(this.SiteCookie.Config) ?? new Hashtable();
                        var userName = this.SiteCookie.Account;
                        var alias = (feildConfig["__ALIAS"] as string) ?? userName;
                        _Account = UMC.Security.Identity.Create(UMC.Data.Utility.Guid(userName, true).Value, userName, alias, (feildConfig["__ROLE"] as string ?? "").Split(','), (feildConfig["__ORGA"] as string ?? "").Split(','));
                    }
                }
                return _Account;
            }
        }



        HeadValues Cookies = new HeadValues();
        CookieSet cookieSet, domainCookie;
        void InitClientCookie(StringValue domain)
        {

            var host = new StringValue(this.Domain.Host.UTF8());
            if (this.Site.IsUnion)
            {
                var parant = DataFactory.Instance().Cookie($"{this.Site.Root}_Main", User.Id.Value, this.SiteCookie.IndexValue.Value);

                domainCookie = new CookieSet(parant?.CookieValue);

                if (User.IsAuthenticated)
                {
                    if ((this.SiteCookie.LoginTime ?? 0) < this.Context.Token.LoginTime)
                    {

                        this.Context.Loger.Info().Write("访问了").Write(this.Site.Caption).Write(domain.Span).End();

                        cookieSet.ClearExpires();

                        ClearCookie(domain);

                        DataFactory.Instance().Put(new Entities.Cookie
                        {
                            Domain = _RootKey,
                            user_id = User.Id.Value,
                            Time = DateTime.Now,
                            IndexValue = this.SiteCookie.IndexValue,
                            LoginTime = Utility.TimeSpan(),
                            CookieValue = cookieSet.IsChange ? cookieSet.ToBytes() : null
                        });
                        cookieSet.IsChange = false;
                        if (domain.IsEmpty)
                        {
                            domainCookie.ClearExpires();
                            if (domainCookie.IsChange)
                            {
                                DataFactory.Instance().Put(new Entities.Cookie
                                {
                                    Domain = parant.Domain,
                                    user_id = User.Id.Value,
                                    Time = DateTime.Now,
                                    IndexValue = parant.IndexValue,
                                    LoginTime = Utility.TimeSpan(),
                                    CookieValue = domainCookie.IsChange ? domainCookie.ToBytes() : null
                                });
                                domainCookie.IsChange = false;
                            }
                        }

                    }


                }
                domainCookie.WirteDomain(this.Cookies, host, this.RawUrl);
                cookieSet.WirteValue(Cookies, host, this.RawUrl);
                var ms = this.Context.Cookies;
                if (this.Site.IsOutputAllCookies)
                {
                    foreach (var cookie in ms.Span)
                    {
                        Cookies[cookie.Name] = cookie.Value;
                    }
                }
                else
                {
                    foreach (var cookie in this.Site.OutputCookies.Span)
                    {
                        if (ms.TryGet(cookie.Name.Span, out var headValue))
                        {
                            if (cookie.Domain.Span.SequenceEqual(domain.Span))
                            {
                                Cookies[cookie.Name] = headValue.Value;
                            }

                        }
                    }
                }

            }
            else
            {
                if (User.IsAuthenticated)
                {
                    if ((this.SiteCookie.LoginTime ?? 0) < this.Context.Token.LoginTime)
                    {
                        cookieSet.ClearExpires();
                        ClearCookie(domain);
                        if (String.IsNullOrEmpty(this.SiteCookie.Account))
                        {
                            this.Context.Loger.Info().Write("访问了").Write(this.Site.Caption).End();

                        }
                        else
                        {
                            this.Context.Loger.Info().Write($"用{this.SiteCookie.Account}访问了").Write(this.Site.Caption).End();
                        }

                        DataFactory.Instance().Put(new Entities.Cookie
                        {
                            Domain = _RootKey,
                            user_id = User.Id.Value,
                            Time = DateTime.Now,
                            IndexValue = this.SiteCookie.IndexValue,
                            LoginTime = Utility.TimeSpan(),
                            CookieValue = cookieSet.IsChange ? cookieSet.ToBytes() : null
                        });
                        cookieSet.IsChange = false;
                    }
                }
                domainCookie = new CookieSet(Array.Empty<byte>());
                cookieSet.WirteValue(Cookies, host, this.RawUrl);

                var ms = this.Context.Cookies;
                foreach (var cookie in this.Site.OutputCookies.Span)
                {
                    if (ms.TryGet(cookie.Name.Span, out var headValue) && cookie.Domain.IsEmpty)
                    {
                        Cookies[cookie.Name] = headValue.Value;
                    }
                }

            }



        }
        Set<Tuple<int, StringValue>> OuterCookies = new Set<Tuple<int, StringValue>>(Comparer<Tuple<int, StringValue>>.Create((x, y) =>
        {
            return x.Item2.Span.Slice(0, x.Item1).SequenceCompareTo(y.Item2.Span.Slice(0, y.Item1));
        }));
        public int StaticModel
        {
            get;
            private set;
        }
        internal static StringValue StaticPage = new StringValue(".gif,.ico,.svg,.bmp,.png,.jpg,.jpeg,.css,.less,.sass,.scss,.js,.webp,.jsx,.coffee,.ts,.ttf,.woff,.woff2,.wasm");
        public static int CheckStaticPage(SiteConfig config, Span<byte> path)
        {
            foreach (var v in config.StatusPage)
            {

                if (path.StartsWith(v.StartPath.Span) == false)
                {
                    continue;
                }
                if (path.EndsWith(v.EndPath.Span) == false)
                {
                    continue;
                }
                return v.Value;
            }
            return CheckStaticPage(path);



        }
        public static int CheckStaticPage(Span<byte> path)
        {
            var v1 = path.LastIndexOf(HttpReplacer.BytePOINT);
            if (v1 > -1)
            {
                if (StaticPage.Contains(path.Slice(v1), true))
                {
                    return 0;
                }
            }
            return -1;
        }
        public StringValue RawUrl
        {
            get;
            private set;
        }
        public UMC.Net.NetContext Context
        {
            get;
            private set;
        }
        void SignOutHtml()
        {

            var sb = new StringWriter();
            sb.WriteLine("<div  class=\"umc-proxy-acounts\">");
            sb.WriteLine("<a class=\"home\" href=\"/UMC.TOP\">回到云桌面</a>");
            sb.WriteLine("<a class=\"signout\" href=\"/UMC.SignOut\">关闭登录</a>");
            sb.WriteLine("<a class=\"login\" href=\"/UMC.Login\">继续工作</a>");
            sb.WriteLine("</div>");
            sb.WriteLine($"<div style=\"color: #999; line-height: 50px; text-align: center;\">检测到您，正在退出{this.Site.Caption}!!!");
            sb.WriteLine("</div>");

            this.Context.AddHeader(StringValue.CacheControl, "no-store");
            this.Context.ContentType = StringValue.ContentTypeHtml;//"text/html; charset=UTF-8";

            using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                  .GetManifestResourceStream("UMC.ITME.Resources.login-html.html"))
            {
                var str = new System.IO.StreamReader(stream).ReadToEnd();
                this.Context.Output.Write(new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                {
                    var key = g.Groups["key"].Value.ToLower();
                    switch (key)
                    {

                        case "title":
                            return this.Site.Caption;
                        case "html":
                            return sb.ToString();
                    }
                    return "";

                }));

            }


        }
        void LoginCheckHtml()
        {

            var sb = new StringWriter();

            sb.WriteLine("<div style=\"margin-left: 50px;\" class=\"umc-proxy-acounts\">");
            sb.WriteLine("<a class=\"auto\" href=\"/UMC.Login/Auto\">免密自动绑定</a>");

            sb.WriteLine("<a class=\"input\" href=\"/UMC.Login/Input\">手输账户绑定</a>");

            sb.WriteLine("</div>");
            sb.WriteLine($"<div style=\"color: #999; line-height: 50px; text-align: center;\">推荐{this.Site.Caption}使用“免密自动绑定”，更简便。");
            sb.WriteLine("</div>");

            this.Context.AddHeader(StringValue.CacheControl, "no-store");
            this.Context.ContentType = StringValue.ContentTypeHtml;

            using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                  .GetManifestResourceStream("UMC.ITME.Resources.login-html.html"))
            {
                var str = new System.IO.StreamReader(stream).ReadToEnd();
                this.Context.Output.Write(new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                {
                    var key = g.Groups["key"].Value.ToLower();
                    switch (key)
                    {

                        case "title":
                            return "请选择账户绑定方式";
                        case "html":
                            return sb.ToString();
                    }
                    return "";

                }));

            }

        }
        bool CheckAccountSelectHtml()
        {

            var scookies = DataFactory.Instance().Cookies(this.Site.Root, User.Id.Value).Where(r => String.IsNullOrEmpty(r.Account) == false).OrderBy(r => r.IndexValue).ToList();
            if (scookies.Count > 1)
            {
                var sb = new StringWriter();
                if (scookies.Count == 2)
                {
                    sb.WriteLine("<div style=\"margin-left: 50px;\" class=\"umc-proxy-acounts\">");
                }
                else
                {
                    sb.WriteLine("<div class=\"umc-proxy-acounts\">");
                }
                foreach (var sc in scookies)
                {
                    sb.WriteLine("<a href=\"/UMC.Login/{0}\">{1}</a>", sc.IndexValue ?? 0, sc.Account);

                }
                sb.WriteLine("</div>");

                this.Context.AddHeader(StringValue.CacheControl, "no-store");
                this.Context.ContentType = StringValue.ContentTypeHtml;//"text/html; charset=UTF-8";
                using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                      .GetManifestResourceStream("UMC.ITME.Resources.login-html.html"))
                {
                    var str = new System.IO.StreamReader(stream).ReadToEnd();
                    this.Context.Output.Write(new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                    {
                        var key = g.Groups["key"].Value.ToLower();
                        switch (key)
                        {
                            case "title":
                                return "您有多个账户，请选择";
                            case "html":
                                return sb.ToString();

                        }
                        return "";

                    }));

                }
                return true;
            }
            return false;

        }
        void LoginHtml(String error, bool isUser)
        {

            using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                     .GetManifestResourceStream("UMC.ITME.Resources.login.html"))
            {
                this.Context.AddHeader(StringValue.CacheControl, "no-store");
                this.Context.ContentType = StringValue.ContentTypeHtml;

                var str = new System.IO.StreamReader(stream).ReadToEnd();
                var v = new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                {
                    var key = g.Groups["key"].Value.ToLower();
                    switch (key)
                    {
                        case "user":
                            var Str = "";
                            if (isUser)
                            {
                                using (System.IO.Stream stream2 = typeof(HttpProxy).Assembly
                                                   .GetManifestResourceStream("UMC.ITME.Resources.user.html"))
                                {
                                    Str = new System.IO.StreamReader(stream2).ReadToEnd().Replace("{name}", this.SiteCookie.Account ?? this.Context.Token.Username);
                                }
                                if (this.SiteCookie.IndexValue > 0)
                                {
                                    return Str;
                                }
                                if (SiteConfig.CheckMime(this.Site.Update))
                                {
                                    switch (this.Site.Site.UserModel ?? Entities.UserModel.Standard)
                                    {
                                        case Entities.UserModel.Check:
                                            return Str;
                                    }

                                    var updateModel = this.Site.Update.UpdateModel ?? "Selected";
                                    switch (updateModel)
                                    {
                                        case "Select":
                                        case "Selected":
                                        case "Compel":
                                            using (System.IO.Stream stream2 = typeof(HttpProxy).Assembly
                                                             .GetManifestResourceStream($"UMC.ITME.Resources.pwd-{updateModel}.html"))
                                            {
                                                Str += new System.IO.StreamReader(stream2).ReadToEnd();
                                            }
                                            break;
                                        default:
                                            break;
                                    }
                                }


                            }
                            return Str;
                        case "action":
                            var callback = this.Context.QueryString.Get("callback");

                            if (String.IsNullOrEmpty(callback) == false)
                            {
                                return $"?callback={Uri.EscapeDataString(callback)}";
                            }
                            else if (this.RawUrl.Span.StartsWith("/UMC.Login"u8))
                            {

                                return String.Empty;
                            }
                            else
                            {
                                return $"/UMC.Login/Go?callback={Uri.EscapeDataString(this.RawUrl.Span.UTF8())}";
                            }
                        case "home":
                            return "";
                        case "title":
                            return isUser ? $"{this.Site.Caption}账户绑定" : $"{this.Site.Caption}登录";
                        case "error":
                            return error;
                        case "fields":
                            return UMC.Data.JSON.Serialize(this.FieldHtml(isUser));
                    }
                    return "";

                });
                this.Context.Output.Write(v);

            }
        }

        WebMeta[] FieldHtml(bool isUser)
        {
            var user = this.Context.Token.Identity();

            var hash = new Hashtable();

            var matchEvaluator = Match(hash, isUser ? "{Username}" : this.SiteCookie.Account, "", "");

            var list = new List<WebMeta>();
            foreach (var fd in this.Site.Login.Feilds)
            {
                var script = fd.Script;
                if (String.IsNullOrEmpty(script))
                {
                    if (String.Equals(fd.Content, "image") == false)
                    {
                        continue;
                    }
                }
                else if (script.StartsWith("[") == false)
                {
                    continue;
                }

                this.Isurlencoded = false;
                var fConfig = new WebMeta().Put("name", fd.Name).Put("title", fd.Caption);
                var changes = new List<String>();
                var rawUrl = fd.RawUrl;

                bool isOcrvalueQuery = false;

                if (String.IsNullOrEmpty(rawUrl) == false)
                {
                    var getUrl = Regex.Replace(rawUrl, matchEvaluator);
                    var ms = Regex.Matches(getUrl);
                    if (ms.Count > 0)
                    {

                        for (var i = 0; i < ms.Count; i++)
                        {
                            var cKey = ms[i].Groups["key"].Value;
                            if (changes.Exists(c => cKey == c) == false)
                                changes.Add(cKey);
                        }

                    }

                    var value = fd.Content ?? String.Empty;
                    // var Method = fd.Method ?? StringValue.GET;
                    switch (fd.Method)
                    {
                        case HttpMethod.POST:
                        case HttpMethod.PUT:
                            {
                                var valResult = Regex.Replace(value, matchEvaluator);

                                ms = Regex.Matches(valResult);
                                if (ms.Count > 0)
                                {
                                    for (var i = 0; i < ms.Count; i++)
                                    {
                                        var cKey = ms[i].Groups["key"].Value;
                                        if (changes.Exists(c => cKey == c) == false)
                                            changes.Add(cKey);
                                    }

                                }
                            }
                            break;
                        case HttpMethod.GET:
                            {
                                isOcrvalueQuery = String.Equals(script, "verifyOcr") || String.Equals("image", value, StringComparison.CurrentCultureIgnoreCase);

                            }
                            break;
                    }
                }
                if (isOcrvalueQuery)
                {
                    fConfig.Put("url", rawUrl);
                }
                else if (changes.Count > 0)
                {
                    fConfig.Put("change", String.Join(",", changes.ToArray()));
                }
                else
                {
                    fConfig.Put("data", UMC.Data.JSON.Expression(GetConfig(fd, matchEvaluator)));
                }
                list.Add(fConfig);

            }
            return list.ToArray();
        }

        void Update(Hashtable feildConfig, HeadValues form)
        {

            var newPass = UMC.Data.Utility.Guid(Guid.NewGuid());
            if (XHR(this.Site.Update, form, feildConfig, newPass))
            {
                var userM = (this.SiteCookie.Model ?? Entities.AccountModel.Standard) | Entities.AccountModel.Changed;
                this.Password = newPass;
                this.SiteCookie.Model = userM;
                this.Context.Loger.Info().Write("更新了在").Write(this.Site.Caption).Write(this.SiteCookie.Account).Write("的密码").End();
            }
        }
        String GetNode(String file, String valResult)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo("node", $"{file} {valResult}")
            {
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            using (Process process = Process.Start(startInfo))
            {
                try
                {
                    using (StreamReader reader = process?.StandardOutput)
                    {

                        string stdout = reader.ReadToEnd();
                        reader.Close();

                        return stdout;
                    }

                }
                finally
                {
                    process?.WaitForExit();
                    process?.Dispose();
                    GC.Collect();
                }
            }
        }
        String GetNode(MimeConfig login, MatchEvaluator matchEvaluator)
        {
            var rawUrl = login.RawUrl.Substring(3);
            var value = login.Content ?? String.Empty;
            this.Isurlencoded = true;
            var valResult = Regex.Replace(value, matchEvaluator);
            string nodeJsScriptPath = Data.Reflection.ConfigPath($"Static/Nodes/{rawUrl}.js");

            var stdout = GetNode(nodeJsScriptPath, valResult);
            if (String.IsNullOrEmpty(stdout))
            {
                errorMsg = $"{rawUrl}.js输出为空,请联系管理员";
                return "{}";
            }
            else
            {
                return stdout;
            }

        }
        String GetConfig(MimeConfig login, MatchEvaluator matchEvaluator)
        {
            var script = login.Script?.Trim() ?? String.Empty;
            if ((script.StartsWith("{") && script.EndsWith("}")) || (script.StartsWith("[") && script.EndsWith("]")))
            {
                return Regex.Replace(script, matchEvaluator);
            }
            if (String.IsNullOrEmpty(login.RawUrl))
            {
                errorMsg = $"未配置请求的Url";
                return "[]";

            }
            this.Isurlencoded = true;

            var PathAndQuery = Regex.Replace(login.RawUrl, matchEvaluator);


            if (login.RawUrl.StartsWith("/$/"))
            {
                return UMC.Data.JSON.Serialize(GetKeyValue(new StringValue(GetNode(login, matchEvaluator)), script));
            }
            var Method = login.Method;// ?? StringValue.GET;

            String valResult = null;
            var webr = this.Context.Transfer(login.Domain ?? Domain);
            webr.RawUrl = this.Context.Memory.Rent(PathAndQuery);
            var value = login.Content ?? String.Empty;

            switch (Method)
            {
                case HttpMethod.POST:
                case HttpMethod.PUT:

                    var ContentType = login.ContentType;
                    if (ContentType.IsEmpty)
                    {
                        this.Isurlencoded = false;

                        valResult = Regex.Replace(value, matchEvaluator);
                    }
                    else
                    {
                        this.Isurlencoded = ContentType.Contains("urlencoded"u8, true);

                        valResult = Regex.Replace(this.Isurlencoded ? value.Trim() : value, matchEvaluator);

                        webr.ContentType = ContentType;

                    }
                    break;
            }
            var resultStr = "{}";
            WebServlet.WebHeaderConf(webr, login.Headers.Span, this.Context, this.SiteCookie.Account);

            using (var mre = new ManualResetEvent(false))
            {
                bool isTryAgain = false;
                Action ReqConfigXhr = null;
                ReqConfigXhr = () =>
                {
                    this.Reqesut(webr).Net(Method, valResult, res =>
                    {
                        this.SetCookie(res);

                        if (res.ContentType?.Contains("image/"u8) == true)
                        {
                            var fileName = System.IO.Path.GetTempFileName();
                            var ms = File.Open(fileName, FileMode.Create);
                            res.ReadAsData((b, i, c) =>
                            {
                                if (c == 0 && b.Length == 0)
                                {
                                    if (i == -1)
                                    {
                                        ms.Close();
                                        ms.Dispose();

                                        if (isTryAgain == false)
                                        {
                                            isTryAgain = true;
                                            ReqConfigXhr();
                                        }
                                        else
                                        {
                                            mre.Set();
                                        }

                                    }
                                    else
                                    {
                                        ms.Flush();
                                        ms.Close();
                                        ms.Dispose();

                                        string nodeJsScriptPath = Data.Reflection.ConfigPath($"Static/Nodes/ocr.js");
                                        if (System.IO.File.Exists(nodeJsScriptPath))
                                        {
                                            resultStr = GetNode(nodeJsScriptPath, fileName + " " + login.Name);
                                            if (this.IsLog)
                                            {
                                                this.Context.Loger.Debug().Write(resultStr).End();
                                            }

                                        }
                                        else
                                        {

                                            errorMsg = "请联系工程师,导入ocr.js文件";
                                            resultStr = "[]";
                                        }


                                        mre.Set();
                                    }
                                }
                                else
                                {
                                    ms.Write(b, i, c);
                                }
                            });

                        }
                        else
                        {
                            res.ReadAsStringValue(str =>
                            {

                                if (this.IsLog == true)
                                {

                                    var loger = this.Context.Loger.Debug();
                                    loger.Write(Mime.Method(Method).Span);
                                    loger.Write(":");
                                    loger.Write(PathAndQuery);

                                    loger.Write(Mime.RowEnd);

                                    HeadValuesLog(loger, webr.Headers);
                                    if (String.IsNullOrEmpty(valResult) == false)
                                    {
                                        loger.Write(valResult);
                                        loger.Write(Mime.RowEnd);
                                    }
                                    loger.Write($"{res.ProtocolVersion} {res.StatusCode} {res.StatusDescription}");//, res.ProtocolVersion, (int)res.StatusCode, res.StatusDescription);

                                    loger.Write(Mime.RowEnd);

                                    HeadValuesLog(loger, res.Headers);
                                    loger.Write(str.Span);
                                    loger.Write(Mime.RowEnd);
                                    loger.End();

                                }
                                if (res.StatusCode == HttpStatusCode.OK && String.IsNullOrEmpty(script) == false && String.Equals(script, "none", StringComparison.CurrentCultureIgnoreCase) == false)
                                {
                                    resultStr = UMC.Data.JSON.Serialize(GetKeyValue(str, script));
                                }
                                mre.Set();
                            }, r => mre.Set());
                        }
                    });
                };
                ReqConfigXhr();
                mre.WaitOne();
            }
            return resultStr;
        }
        Object GetKeyValue(StringValue html2, string nvConfig)
        {
            var html = html2.Span;
            if (nvConfig.StartsWith("[") && nvConfig.Contains("]:"))
            {
                var tfds = new List<String>();

                var keyIndex = nvConfig.IndexOf(':');
                var nv = nvConfig.Substring(0, keyIndex).Trim('[', ']');
                if (String.IsNullOrEmpty(nv) == false)
                {
                    var nvs = nv.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var k in nvs)
                    {
                        var v = k.Trim();
                        if (String.IsNullOrEmpty(v) == false)
                        {
                            tfds.Add(v);
                        }
                    }
                }

                var keyN = nvConfig.Substring(keyIndex + 1).Trim();


                var sc = UMC.Data.JSON.Deserialize(html.UTF8());
                Array array = null;
                if (html.StartsWith("["u8))
                {
                    array = sc as Array;
                }
                else if (sc is Hashtable)
                {
                    var scD = sc as Hashtable;
                    if (scD.ContainsKey(keyN))
                    {
                        array = scD[keyN] as Array;
                    }
                    else
                    {
                        int idex = keyN.IndexOf('.');
                        while (idex > 0)
                        {
                            var k = keyN.Substring(0, idex);
                            if (scD.ContainsKey(k))
                            {
                                scD = scD[k] as Hashtable;
                                keyN = keyN.Substring(idex + 1);
                                if (scD.ContainsKey(keyN))
                                {

                                    array = scD[keyN] as Array;
                                    break;
                                }
                                else
                                {
                                    idex = keyN.IndexOf('.');
                                }
                            }
                        }
                    }
                }
                if (array == null)
                {
                    return new int[0];
                }

                var vField = "";
                if (tfds.Count > 0)
                {
                    vField = tfds[tfds.Count - 1];
                    if (tfds.Count > 1)
                    {
                        tfds.RemoveAt(tfds.Count - 1);
                    }
                }
                var list = new List<WebMeta>();

                foreach (var k in array)
                {
                    if (tfds.Count == 0)
                    {
                        list.Add(new WebMeta().Put("Text", k.ToString(), "Value", k.ToString()));
                    }
                    else if (k is Hashtable)
                    {
                        var kd = k as Hashtable;
                        var tkvs = new List<String>();
                        foreach (var tk in tfds)
                        {
                            var v = kd[tk] as string;
                            if (String.IsNullOrEmpty(v) == false)
                            {
                                tkvs.Add(v);
                            }
                        }
                        list.Add(new WebMeta().Put("Text", String.Join("-", tkvs.ToArray())).Put("Value", kd[vField]));

                    }
                }
                return list;

            }
            var nas = SiteConfig.Config(nvConfig);
            var isKey = nas.Contains("KEY-VALUE");
            var vnvs = new Hashtable();

            var formValues = Utility.FromValue(html, isKey);
            var isError = false;
            int valueCount = 0;
            foreach (var name in nas)
            {
                var naSpan = name.UTF8();
                if (String.Equals(name, "KEY-VALUE"))
                {
                    continue;
                }
                else if (String.Equals(name, "KEY-ERROR"))
                {
                    isError = true;
                    continue;
                }
                valueCount++;
                if (formValues.ContainsKey(name))
                {
                    vnvs[name] = formValues[name];
                }
                else
                {
                    int sIndex = html.IndexOf(naSpan);
                    if (sIndex > 1 && sIndex + name.Length < html.Length)
                    {
                        sIndex = sIndex + name.Length;
                        switch (html[sIndex])
                        {
                            case 32: //' '
                            case 34: //'"'
                            case 39://(byte)'\'':
                                if (html[sIndex - 1 - name.Length] == html[sIndex])
                                {

                                    while (sIndex < html.Length)
                                    {
                                        sIndex++;
                                        switch (html[sIndex])
                                        {
                                            case 13://(byte)'\r':
                                            case 9:// (byte)'\t':
                                            case 10:// (byte)'\n':
                                            case 32://(byte)' ':
                                                break;
                                            case 58://(byte)':':
                                            case 61://(byte)'=':
                                                var str = GetHtmlValue(html2, sIndex + 1);
                                                if (str.IsEmpty == false)
                                                {
                                                    vnvs[name.Trim(':', '\'', '"', '=').Trim()] = str.Span.UTF8();
                                                }
                                                sIndex = html.Length;
                                                break;
                                        }
                                    }
                                }
                                break;
                            case 58://(byte)':':
                            case 61://(byte)'=':
                                var str2 = GetHtmlValue(html2, sIndex + 1);
                                if (str2.IsEmpty == false)
                                {
                                    vnvs[name.Trim(':', '\'', '"', '=').Trim()] = str2.Span.UTF8();
                                }
                                break;
                        }
                    }
                }

            }
            if (isError && vnvs.Count != valueCount)
            {
                return "未获取正确的参数";
            }
            return vnvs;
        }
        StringValue GetHtmlValue(StringValue html2, int nIndex)
        {
            var html = html2.Span;

            int start = 0, end = 0;
            byte? startStr = null;

            while (nIndex < html.Length)
            {
                switch (html[nIndex])
                {
                    // case (byte)'\r':
                    // case (byte)'\t':
                    // case (byte)'\n':
                    // case (byte)' ':
                    case 13://(byte)'\r':
                    case 9:// (byte)'\t':
                    case 10:// (byte)'\n':
                    case 32://(byte)' ':

                        if (start > 0 && startStr.HasValue == false)
                        {
                            end = nIndex;
                        }
                        break;
                    case 59:
                    case 44:
                        // case (byte)';':
                        // case (byte)',':
                        if (startStr.HasValue == false)
                        {
                            end = nIndex;
                        }
                        break;

                    case 34: //'"'
                    case 39://(byte)'\'':
                            // case (byte)'"':
                            // case (byte)'\'':
                        if (start == 0)
                        {
                            start = nIndex + 1;
                            startStr = html[nIndex];

                        }
                        else if (html[nIndex] == startStr)
                        {
                            end = nIndex;
                        }
                        break;
                    case 125:// (byte)'}':
                        if (start > 0 && startStr.HasValue == false)
                        {
                            end = nIndex;
                        }
                        break;
                    default:
                        if (start == 0)
                        {
                            start = nIndex;
                        }
                        break;
                }
                if (end > 0)
                {
                    break;
                }
                nIndex++;
            }
            if (start > 0 && start < end)
            {
                return html2.Slice(start, end - start);
            }
            return StringValue.Empty;

        }

        bool IsLog;
        String errorMsg;
        void SetCookie(HeadValue c)
        {

            if (this.Context.Cookies.Count > 0 && this.Site.Site.UserModel != Entities.UserModel.Bridge && CookieSet.TryConvert(c.Value, out var cookie))
            {
                if (this.IsLog)
                    this.Context.Loger.Info().Write(this.Domain.Host).Write(c.Value.Span).End();
                this.Cookies[cookie.Name] = cookie.Value;
                if (this.Site.IsUnion)
                {
                    if (cookie.Domain.IsEmpty == false)
                    {
                        this.domainCookie.Append(cookie);
                    }
                    else
                    {
                        this.cookieSet.Append(cookie);
                    }
                }
                else
                {
                    this.cookieSet.Append(cookie);
                }
                if (this.Site.IsOutputAllCookies || this.Site.OutputCookies.Contains(cookie))
                {

                    this.OuterCookies.Put(Tuple.Create(cookie.Name.Length + 1, c.Value));
                }
            }
            else
            {
                this.OuterCookies.Put(Tuple.Create(c.Value.Span.IndexOf((byte)'=') + 1, c.Value));
            }

        }
        void SetCookie(NetHttpResponse response)
        {
            var span = response.Headers.Span;
            foreach (var k in span)
            {
                switch (k.HeadKey)
                {
                    case MimeHeadKey.SetCookie:
                        this.SetCookie(k);
                        break;
                }
            }
        }


        String ResetPasswork(HeadValues form, SiteConfig siteConfig)
        {

            if (String.IsNullOrEmpty(siteConfig.Site.Account))
            {
                if (this.IsLog == true)
                    this.Context.Loger.Debug().Write("未配置检测账户").End();
                return null;
            }


            var proxy = new HttpProxy(this, siteConfig);

            if (siteConfig.Check.Finish.IsEmpty == false)
            {
                var config = new Hashtable();

                if (proxy.IsLog == true)
                {
                    this.Context.Loger.Info().Write("管理员登录:").End();
                }
                if (siteConfig.Check.IsNotLoginApi || proxy.XHR(siteConfig.Login, form, config, String.Empty))
                {

                    var newPass = UMC.Data.Utility.Guid(Guid.NewGuid());

                    config["Account"] = this.Context.Token.Username;
                    if (proxy.IsLog == true)
                    {
                        this.Context.Loger.Info().Write("检测账户密码:").End();
                    }
                    if (proxy.XHR(siteConfig.Check, form, config, newPass))
                    {
                        if (config.ContainsKey("ResetPasswork"))
                        {
                            return config["ResetPasswork"] as string;
                        }
                        return newPass;
                    }
                    else if (this.IsLog == true)
                    {
                        this.Context.Loger.Info().Write(this.errorMsg).End();
                        // this.Loger.WriteLine(this.errorMsg);
                    }

                }
                else
                {
                    errorMsg = "检测账户登录失败导致不能重置密码,请联系应用管理员";

                    if (this.IsLog == true)
                    {
                        this.Context.Loger.Info().Write("检测账户登录失败导致不能重置密码").End();
                    }
                }
            }
            else
            {
                if (this.IsLog == true)
                {
                    this.Context.Loger.Info().Write("未配置完善账户检测接口").End();
                }

            }
            return null;
        }

        static Regex Regex = new Regex("\\{(?<key>[\\w\\.\\$,\\[\\]_-]+)\\}");
        bool Isurlencoded = true;
        bool XHR(MimeFeildConfig login, HeadValues form, Hashtable FeildConfig, String newPass)
        {
            return XHR(login, form, FeildConfig, newPass, out var _);
        }

        String GetValue(String key, IDictionary FeildConfig, String newPWd)
        {
            switch (key.ToLower())
            {
                case "user":
                    return this.SiteCookie.Account;
                case "pwd":
                    return this.Password;
                case "new":
                    return newPWd;

            }


            var b = FeildConfig[key] as string;
            if (String.IsNullOrEmpty(b) && key.StartsWith("$"))
            {
                return key.Substring(1);
            }
            return b;
        }
        MatchEvaluator Match(Hashtable FeildConfig, String newPass)
        {
            return Match(FeildConfig, this.SiteCookie.Account, this.Password, newPass);
        }
        MatchEvaluator Match(Hashtable FeildConfig, String user, String pd, String newPass)
        {
            Func<String, String> func = (key) =>
             {

                 switch (key.ToLower())
                 {

                     case "user":
                     case "username":
                         return Isurlencoded ? Uri.EscapeDataString(user) : user;
                     case "pwd":
                     case "password":
                         return Isurlencoded ? Uri.EscapeDataString(pd ?? "") : (pd ?? "");
                     case "md5pwd":
                         return UMC.Data.Utility.MD5(pd);
                     case "md5new":
                         return UMC.Data.Utility.MD5(newPass);
                     case "newpwd":
                     case "new":
                         return Isurlencoded ? Uri.EscapeDataString(newPass) : newPass;
                     case "time":
                         return UMC.Data.Utility.TimeSpan().ToString();
                     case "mtime":
                         return UMC.Data.Reflection.TimeSpanMilli(DateTime.Now).ToString();
                     default:
                         var nIndex = key.IndexOf('.');
                         if (nIndex > 0)
                         {
                             string fvalue = "";
                             switch (key.Substring(0, nIndex))
                             {
                                 case "hex":
                                     key = key.Substring(4);
                                     fvalue = GetValue(key, FeildConfig, newPass);
                                     if (String.IsNullOrEmpty(fvalue) == false)
                                     {

                                         return UMC.Data.Utility.Hex(System.Text.Encoding.UTF8.GetBytes(fvalue));
                                     }
                                     break;
                                 case "b64":
                                     key = key.Substring(4);
                                     fvalue = GetValue(key, FeildConfig, newPass);

                                     if (String.IsNullOrEmpty(fvalue) == false)
                                     {
                                         if (this.Isurlencoded)
                                         {
                                             return Uri.EscapeDataString(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fvalue)));
                                         }
                                         else
                                         {
                                             return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fvalue));
                                         }
                                     }
                                     break;
                                 case "md5":
                                     key = key.Substring(4);
                                     {
                                         var isb64 = false;
                                         if (key.EndsWith(".b64"))
                                         {
                                             isb64 = true;
                                             key = key.Substring(0, key.Length - 4);
                                         }

                                         fvalue = GetValue(key, FeildConfig, newPass);
                                         if (String.IsNullOrEmpty(fvalue) == false)
                                         {
                                             byte[] mdata;
                                             using (var md5 = System.Security.Cryptography.MD5.Create())
                                             {
                                                 mdata = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(fvalue));
                                             }
                                             if (isb64)
                                             {
                                                 if (this.Isurlencoded)
                                                 {
                                                     return Uri.EscapeDataString(Convert.ToBase64String(mdata));
                                                 }
                                                 else
                                                 {
                                                     return Convert.ToBase64String(mdata);
                                                 }
                                             }
                                             else
                                             {
                                                 return UMC.Data.Utility.Hex(mdata);

                                             }
                                         }
                                     }
                                     break;

                                 case "s256":
                                     key = key.Substring(5);
                                     {
                                         var isb64 = false;
                                         if (key.EndsWith(".b64"))
                                         {
                                             isb64 = true;
                                             key = key.Substring(0, key.Length - 4);
                                         }
                                         fvalue = GetValue(key, FeildConfig, newPass);
                                         if (String.IsNullOrEmpty(fvalue) == false)
                                         {

                                             var mdata = SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(fvalue));
                                             if (isb64)
                                             {
                                                 if (this.Isurlencoded)
                                                 {
                                                     return Uri.EscapeDataString(Convert.ToBase64String(mdata));
                                                 }
                                                 else
                                                 {
                                                     return Convert.ToBase64String(mdata);
                                                 }
                                             }
                                             else
                                             {
                                                 return UMC.Data.Utility.Hex(mdata);

                                             }
                                         }
                                     }
                                     break;
                                 case "sha1":
                                     key = key.Substring(5);
                                     {
                                         var isb64 = false;
                                         if (key.EndsWith(".b64"))
                                         {
                                             isb64 = true;
                                             key = key.Substring(0, key.Length - 4);
                                         }
                                         fvalue = GetValue(key, FeildConfig, newPass);
                                         if (String.IsNullOrEmpty(fvalue) == false)
                                         {
                                             var mdata = SHA1.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(fvalue));
                                             if (isb64)
                                             {
                                                 if (this.Isurlencoded)
                                                 {
                                                     return Uri.EscapeDataString(Convert.ToBase64String(mdata));
                                                 }
                                                 else
                                                 {
                                                     return Convert.ToBase64String(mdata);
                                                 }
                                             }
                                             else
                                             {
                                                 return UMC.Data.Utility.Hex(mdata);
                                             }

                                         }
                                     }
                                     break;
                                 case "hmac":
                                     key = key.Substring(5);
                                     nIndex = key.IndexOf('.');
                                     if (nIndex > 0)
                                     {

                                         var bpwd = FeildConfig[(key.Substring(0, nIndex))] as string;
                                         if (String.IsNullOrEmpty(bpwd) == false)
                                         {
                                             key = key.Substring(nIndex + 1);

                                             var isb64 = false;
                                             if (key.EndsWith(".b64"))
                                             {
                                                 isb64 = true;
                                                 key = key.Substring(0, key.Length - 4);
                                             }


                                             fvalue = GetValue(key, FeildConfig, newPass);
                                             if (String.IsNullOrEmpty(fvalue) == false)
                                             {
                                                 var mdata = new HMACSHA1(Encoding.UTF8.GetBytes(bpwd)).ComputeHash(Encoding.UTF8.GetBytes(fvalue));

                                                 if (isb64)
                                                 {
                                                     if (this.Isurlencoded)
                                                     {
                                                         return Uri.EscapeDataString(Convert.ToBase64String(mdata));
                                                     }
                                                     else
                                                     {
                                                         return Convert.ToBase64String(mdata);
                                                     }
                                                 }
                                                 else
                                                 {
                                                     return UMC.Data.Utility.Hex(mdata);
                                                 }
                                             }
                                         }
                                     }
                                     break;
                                 case "aes":
                                     key = key.Substring(4);
                                     nIndex = key.IndexOf('.');
                                     if (nIndex > 0)
                                     {
                                         var nkey = FeildConfig[key.Substring(0, nIndex)] as string;
                                         if (String.IsNullOrEmpty(nkey) == false)
                                         {
                                             key = key.Substring(nIndex + 1);
                                             var isb64 = false;
                                             if (key.EndsWith(".b64"))
                                             {
                                                 isb64 = true;
                                                 key = key.Substring(0, key.Length - 4);
                                             }
                                             var keys = key.Split('.');
                                             switch (keys.Length)
                                             {
                                                 case 1:
                                                     fvalue = GetValue(keys[0], FeildConfig, newPass);
                                                     if (String.IsNullOrEmpty(fvalue) == false)
                                                     {
                                                         if (isb64)
                                                         {
                                                             if (this.Isurlencoded)
                                                             {
                                                                 return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, 1)));
                                                             }
                                                             else
                                                             {
                                                                 return Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, 1));
                                                             }
                                                         }
                                                         else
                                                         {
                                                             return UMC.Data.Utility.Hex(UMC.Data.Utility.AES(fvalue, nkey, 1));
                                                         }
                                                     }
                                                     break;
                                                 case 2:
                                                     var iv = FeildConfig[keys[0]] as string;
                                                     fvalue = GetValue(keys[1], FeildConfig, newPass);
                                                     if (String.IsNullOrEmpty(fvalue) == false)
                                                     {
                                                         if (String.IsNullOrEmpty(iv))
                                                         {
                                                             var iterations = UMC.Data.Utility.IntParse(keys[0], -1);
                                                             if (iterations > 0)
                                                             {
                                                                 if (isb64)
                                                                 {
                                                                     if (this.Isurlencoded)
                                                                     {
                                                                         return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, iterations)));
                                                                     }
                                                                     else
                                                                     {
                                                                         return Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, iterations));
                                                                     }
                                                                 }
                                                                 else
                                                                 {
                                                                     return UMC.Data.Utility.Hex(UMC.Data.Utility.AES(fvalue, nkey, iterations));
                                                                 }
                                                             }
                                                         }
                                                         else
                                                         {
                                                             if (isb64)
                                                             {
                                                                 if (this.Isurlencoded)
                                                                 {
                                                                     return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, iv)));
                                                                 }
                                                                 else
                                                                 {
                                                                     return Convert.ToBase64String(UMC.Data.Utility.AES(fvalue, nkey, iv));
                                                                 }
                                                             }
                                                             else
                                                             {
                                                                 return UMC.Data.Utility.Hex(UMC.Data.Utility.AES(fvalue, nkey, iv));
                                                             }
                                                         }
                                                     }
                                                     break;
                                             }
                                         }
                                     }

                                     break;
                                 case "des":
                                     key = key.Substring(4);
                                     nIndex = key.IndexOf('.');
                                     if (nIndex > 0)
                                     {
                                         var nkey = FeildConfig[key.Substring(0, nIndex)] as string;
                                         if (String.IsNullOrEmpty(nkey) == false)
                                         {
                                             key = key.Substring(nIndex + 1);
                                             var isb64 = false;
                                             if (key.EndsWith(".b64"))
                                             {
                                                 isb64 = true;
                                                 key = key.Substring(0, key.Length - 4);
                                             }
                                             var keys = key.Split('.');
                                             switch (keys.Length)
                                             {
                                                 case 1:
                                                     fvalue = GetValue(keys[0], FeildConfig, newPass);
                                                     if (String.IsNullOrEmpty(fvalue) == false)
                                                     {
                                                         if (isb64)
                                                         {
                                                             if (this.Isurlencoded)
                                                             {
                                                                 return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, 1)));
                                                             }
                                                             else
                                                             {
                                                                 return Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, 1));
                                                             }
                                                         }
                                                         else
                                                         {
                                                             return UMC.Data.Utility.Hex(UMC.Data.Utility.DES(fvalue, nkey, 1));
                                                         }
                                                     }
                                                     break;
                                                 case 2:
                                                     var iv = FeildConfig[keys[0]] as string;
                                                     fvalue = GetValue(keys[1], FeildConfig, newPass);
                                                     if (String.IsNullOrEmpty(fvalue) == false)
                                                     {
                                                         if (String.IsNullOrEmpty(iv))
                                                         {
                                                             var iterations = UMC.Data.Utility.IntParse(keys[0], -1);
                                                             if (iterations > 0)
                                                             {
                                                                 if (isb64)
                                                                 {
                                                                     if (this.Isurlencoded)
                                                                     {
                                                                         return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, iterations)));
                                                                     }
                                                                     else
                                                                     {
                                                                         return Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, iterations));
                                                                     }
                                                                 }
                                                                 else
                                                                 {
                                                                     return UMC.Data.Utility.Hex(UMC.Data.Utility.DES(fvalue, nkey, iterations));
                                                                 }
                                                             }
                                                         }
                                                         else
                                                         {
                                                             if (isb64)
                                                             {
                                                                 if (this.Isurlencoded)
                                                                 {
                                                                     return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, iv)));
                                                                 }
                                                                 else
                                                                 {
                                                                     return Convert.ToBase64String(UMC.Data.Utility.DES(fvalue, nkey, iv));
                                                                 }
                                                             }
                                                             else
                                                             {
                                                                 return UMC.Data.Utility.Hex(UMC.Data.Utility.DES(fvalue, nkey, iv));
                                                             }
                                                         }
                                                     }
                                                     break;
                                             }
                                         }
                                     }

                                     break;
                                 case "pem":
                                     key = key.Substring(4);
                                     nIndex = key.IndexOf('.');
                                     if (nIndex > 0)
                                     {
                                         var pem = FeildConfig[key.Substring(0, nIndex)] as string;
                                         if (String.IsNullOrEmpty(pem) == false)
                                         {
                                             key = key.Substring(nIndex + 1);

                                             var isb64 = false;
                                             if (key.EndsWith(".b64"))
                                             {
                                                 isb64 = true;
                                                 key = key.Substring(0, key.Length - 4);
                                             }
                                             fvalue = GetValue(key, FeildConfig, newPass);
                                             if (String.IsNullOrEmpty(fvalue) == false)
                                             {
                                                 if (isb64)
                                                 {
                                                     if (this.Isurlencoded)
                                                     {
                                                         return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.RSA(pem, fvalue)));
                                                     }
                                                     else
                                                     {
                                                         return Convert.ToBase64String(UMC.Data.Utility.RSA(pem, fvalue));
                                                     }
                                                 }
                                                 else
                                                 {
                                                     return UMC.Data.Utility.Hex(UMC.Data.Utility.RSA(pem, fvalue));
                                                 }
                                             }

                                         }
                                     }
                                     break;
                                 case "rsa":
                                     key = key.Substring(4);
                                     nIndex = key.IndexOf('.');
                                     if (nIndex > 0)
                                     {
                                         var n = FeildConfig[key.Substring(0, nIndex)] as string;
                                         if (String.IsNullOrEmpty(n) == false)
                                         {
                                             var isb64 = false;
                                             if (key.EndsWith(".b64"))
                                             {
                                                 isb64 = true;
                                                 key = key.Substring(0, key.Length - 4);
                                             }
                                             key = key.Substring(nIndex + 1);
                                             nIndex = key.IndexOf('.');

                                             if (nIndex > 0)
                                             {
                                                 var e = FeildConfig[key.Substring(0, nIndex)] as string;
                                                 key = key.Substring(nIndex + 1);

                                                 fvalue = GetValue(key, FeildConfig, newPass);
                                                 if (fvalue != null)
                                                 {
                                                     if (isb64)
                                                     {
                                                         if (this.Isurlencoded)
                                                         {
                                                             return Uri.EscapeDataString(Convert.ToBase64String(UMC.Data.Utility.RSA(n, e, fvalue)));
                                                         }
                                                         else
                                                         {
                                                             return Convert.ToBase64String(UMC.Data.Utility.RSA(n, e, fvalue));
                                                         }
                                                     }
                                                     else
                                                     {
                                                         return UMC.Data.Utility.Hex(UMC.Data.Utility.RSA(n, e, fvalue));
                                                     }
                                                 }
                                             }
                                         }
                                     }

                                     break;
                             }
                         }

                         if (FeildConfig.ContainsKey(key))
                         {
                             return Isurlencoded ? Uri.EscapeDataString(FeildConfig[key] as string ?? "") : FeildConfig[key] as string;
                         }
                         else
                         {
                             var cookie = this.Context.Cookies.Get(key.UTF8());
                             if (cookie.IsEmpty == false)
                             {
                                 return Isurlencoded ? Uri.EscapeDataString(cookie.Span.UTF8()) : cookie.Span.UTF8();
                             }
                         }
                         return null;
                 }
             };

            MatchEvaluator matchEvaluator = r =>
            {

                var key = r.Groups["key"].Value;
                var kIndex = key.IndexOf('[');
                if (kIndex > 0)
                {
                    var value = func(key.Substring(0, kIndex));
                    if (value == null)
                    {
                        return r.Value;
                    }
                    else
                    {
                        var sValue = key.Substring(kIndex + 1).Trim('[', ']').Trim().Split(',');

                        switch (sValue.Length)
                        {
                            case 1:
                                return value.Substring(0, UMC.Data.Utility.IntParse(sValue[0], 0));
                            case 2:
                                return value.Substring(UMC.Data.Utility.IntParse(sValue[0], 0), UMC.Data.Utility.IntParse(sValue[1], value.Length));

                            default:
                                return r.Value;
                        }

                    }
                }
                else
                {
                    return func(key) ?? r.Value;
                }

            };
            return matchEvaluator;
        }
        StringValue _LoginRedirectLocation = StringValue.Empty;
        bool CheckRes(StringValue finish, NetHttpResponse response, StringValue body)
        {
            var span = finish.Span;
            if (span.StartsWith("H:"u8))
            {
                var key = span.Slice(2);
                var keyIndex = key.IndexOf((byte)':');
                if (keyIndex > 0)
                {
                    var v = key.Slice(keyIndex + 1);//.Trim();
                    key = key.Slice(0, keyIndex);
                    var keyValue = response.Headers.Get(key);
                    if (keyValue.IsEmpty == false)
                    {
                        if (v.SequenceEqual(keyValue.Span))
                        {
                            return true;

                        }
                    }
                }
                else if (response.Headers.Get(key).IsEmpty == false)
                {
                    return true;
                }
            }
            else if (span.StartsWith("HE:"u8))
            {
                var key = span.Slice(3);
                var keyIndex = key.IndexOf((byte)':');
                if (keyIndex > 0)
                {
                    var v = key.Slice(keyIndex + 1);//.Trim();
                    key = key.Slice(0, keyIndex);
                    var keyValue = response.Headers.Get(key);
                    if (keyValue.IsEmpty == false)
                    {
                        if (v.SequenceEqual(keyValue.Span) == false)
                        {
                            return true;
                        }

                    }
                }
                else if (response.Headers.Get(key).IsEmpty)
                {
                    return true;
                }
            }
            else
            {
                switch (response.StatusCode)
                {
                    case HttpStatusCode.Redirect:
                    case HttpStatusCode.RedirectKeepVerb:
                    case HttpStatusCode.RedirectMethod:
                        _LoginRedirectLocation = response.Headers.Get(StringValue.Location.Span);//.Span.UTF8();
                        if (span.SequenceEqual("Url"u8))
                        {
                            return true;
                        }
                        break;
                    case HttpStatusCode.OK:
                        if (this.IsLog == true)
                        {
                            this.Context.Loger.Debug().Write(body.Span).End();
                            // this.Loger.WriteLine();
                        }
                        if (span.StartsWith("E:"u8))
                        {
                            if (body.Contains(span.Slice(2)) == false)
                            {
                                return true;

                            }
                        }
                        else if (span.SequenceEqual("Url"u8) == false)
                        {
                            var start = 0;
                            var end = span.Length;
                            for (var i = 0; i < end; i++)
                            {
                                switch (span[i])
                                {
                                    case 124:
                                        if (body.Contains(span.Slice(start, i - start)))
                                        {
                                            return true;
                                        }
                                        else
                                        {
                                            start = i + 1;
                                        }
                                        break;
                                }
                            }
                            if (body.Contains(span.Slice(start, end - start)))
                            {
                                return true;
                            }
                        }
                        break;
                    default:
                        return false;

                }


            }
            return false;
        }
        bool XHR(MimeFeildConfig login, HeadValues form, Hashtable FeildConfig, String newPass, out NetHttpResponse httpResponse)
        {
            errorMsg = String.Empty;
            httpResponse = null;
            if (login.Finish.IsEmpty == false)
            {

                if (String.IsNullOrEmpty(this.SiteCookie.Account) && this.Password == null)
                {
                    return false;
                }
                var username = this.SiteCookie.Account;
                var Password = this.Password;

                var matchEvaluator = Match(FeildConfig, newPass);

                this.Isurlencoded = true;

                foreach (var mime in login.Feilds)
                {

                    var fvalue = form.Get(mime.Name);
                    if (String.IsNullOrEmpty(fvalue))
                    {

                        var obj = UMC.Data.JSON.Deserialize(GetConfig(mime, matchEvaluator));

                        if (obj is Array)
                        {
                            Array array = obj as Array;
                            switch (array.Length)
                            {
                                case 0:
                                    return false;
                                case 1:
                                    var h = array.GetValue(0) as Hashtable;
                                    if (h != null)
                                    {
                                        var fValue = h["Value"] as string;
                                        FeildConfig[mime.Name] = h["Value"];
                                        if (String.IsNullOrEmpty(fValue))
                                        {
                                            errorMsg = $"获取到{mime.Caption}的格式不正确";
                                            return false;
                                        }
                                    }
                                    else
                                    {
                                        errorMsg = $"获取到{mime.Caption}的格式不正确";
                                        return false;
                                    }
                                    break;
                                default:
                                    if (mime.IsRememberValue == false || FeildConfig.ContainsKey(mime.Name) == false)
                                    {

                                        if (String.IsNullOrEmpty(mime.DefautValue) == false)
                                        {
                                            var sKey = SiteConfig.Config(mime.DefautValue);
                                            if (sKey.Length > 0)
                                            {
                                                int iNdex = 0;
                                                for (; iNdex < array.Length; iNdex++)
                                                {
                                                    var val = array.GetValue(iNdex) as Hashtable;
                                                    if (val != null)
                                                    {
                                                        var fValue = val["Value"] as string;
                                                        if (String.Equals(fValue, sKey[0]))
                                                        {
                                                            FeildConfig[mime.Name] = fValue;
                                                            FeildConfig[mime.Name + "_Text"] = val["Text"];
                                                            break;
                                                        }
                                                    }
                                                }
                                                if (iNdex == array.Length)
                                                {
                                                    errorMsg = $"请选择{mime.Caption}";
                                                    return false;
                                                }
                                            }
                                            else
                                            {
                                                errorMsg = $"请选择{mime.Caption}";
                                                return false;
                                            }
                                        }
                                        else
                                        {
                                            errorMsg = $"请选择{mime.Caption}";
                                            return false;
                                        }
                                    }
                                    break;
                            }
                        }
                        else if (obj is Hashtable)
                        {
                            var ms = (obj as Hashtable).GetEnumerator();
                            while (ms.MoveNext())
                            {
                                FeildConfig[ms.Key] = ms.Value;
                            }
                        }
                        else
                        {
                            errorMsg = $"获取到{mime.Caption}的格式不正确";
                            return false;
                        }
                    }
                    else
                    {
                        String fText = form.Get(mime.Name + "_Text");
                        if (String.IsNullOrEmpty(fText) == false)
                        {

                            FeildConfig[mime.Name + "_Text"] = fText;
                        }
                        FeildConfig[mime.Name] = fvalue;
                    }
                }


                var rawUrl = login.RawUrl;
                if (String.IsNullOrEmpty(rawUrl))
                {
                    errorMsg = "接口请求地址未配置";
                    return false;

                }

                this.Isurlencoded = true;


                var PathAndQuery = Regex.Replace(rawUrl, matchEvaluator);


                var Method = login.Method;// ?? StringValue.GET;

                var webR = this.Context.Transfer(login.Domain ?? this.Domain);

                webR.RawUrl = this.Context.Memory.Rent(PathAndQuery);
                WebServlet.WebHeaderConf(webR, login.Headers.Span, this.Context, this.SiteCookie.Account);
                // webR.in
                String valResult = null;
                switch (Method)
                {
                    case HttpMethod.POST:
                    case HttpMethod.PUT:

                        {
                            var value = login.Content;
                            var ContentType = login.ContentType;
                            if (ContentType.IsEmpty)
                            {
                                this.Isurlencoded = false;
                            }
                            else
                            {
                                this.Isurlencoded = ContentType.Contains("urlencoded"u8, true);
                                valResult = Regex.Replace(this.Isurlencoded ? value?.Trim() : value, matchEvaluator);
                                webR.ContentType = ContentType;

                            }
                        }
                        break;
                }
                var hvalue = new StringValue(webR.Address.Host);
                this.domainCookie.WirteDomain(this.Cookies, hvalue, webR.RawUrl);
                this.cookieSet.WirteValue(this.Cookies, hvalue, webR.RawUrl);

                NetHttpResponse response = null;
                var mre = new ManualResetEvent(false);
                this.Reqesut(webR).Net(Method, valResult, xhr =>
                {
                    response = xhr;
                    xhr.ReadAsStringValue(v =>
                    {
                        _CheckBody = v;
                        mre?.Set();
                    }, r => mre?.Set());
                });
                mre.WaitOne(12000);
                mre = null;
                if (response == null)
                {
                    _CheckBody = StringValue.Empty;
                    return false;
                }
                httpResponse = response;

                if (this.IsLog == true)
                {
                    var loger = this.Context.Loger.Debug();//.Write(resultStr).End();
                    loger.Write(Mime.Method(Method).Span);
                    loger.Write(":");
                    loger.Write(PathAndQuery);
                    loger.Write(Mime.RowEnd);
                    HeadValuesLog(loger, webR.Headers);
                    loger.Write(valResult);
                    loger.Write(Mime.RowEnd);

                    loger.Write($"{response.ProtocolVersion} {response.StatusCode} {response.StatusDescription}");//, res.ProtocolVersion, (int)res.StatusCode, res.StatusDescription);

                    loger.Write(Mime.RowEnd);

                    HeadValuesLog(loger, response.Headers);
                    loger.Write(_CheckBody.Span);
                    loger.Write(Mime.RowEnd);
                    loger.End();

                }


                this.SetCookie(response);
                return CheckRes(login.Finish, response, _CheckBody);
            }
            else
            {
                errorMsg = "接口配置未完善";
                return false;
            }

        }

        StringValue _CheckBody;
        int RetryCount = 0;
        bool Login(bool isHome, bool isBody, HeadValues form, String apiKey)
        {

            var username = form.Get("Username");
            this.Password = form.Get("Password");

            if (String.IsNullOrEmpty(username) == false)
            {
                this.SiteCookie.Account = username;
            }
            var user = this.Context.Token.Identity();

            if (this.Site.Site.UserModel == Entities.UserModel.Quote)
            {
                if (this.SiteCookie.IndexValue == 0)
                {

                    if (String.IsNullOrEmpty(this.Site.Site.Account) == false && this.Site.Site.Account.StartsWith("@"))
                    {
                        var root = this.Site.Site.Account.Substring(1);
                        this.SiteCookie.Account = DataFactory.Instance().Cookie(root, User.Id.Value, 0)?.Account ?? user.Name;

                        this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(root, this.SiteCookie.user_id.Value.ToString(), "0"));
                        if (String.IsNullOrEmpty(Password))
                        {
                            var home = Data.WebResource.Instance().WebDomain();
                            this.Context.Redirect($"{this.Context.Scheme}://{root}{WebServlet.DomainUnion}{home}/UMC.Login?callback={Uri.EscapeDataString(this.Context.Url.AbsoluteUri)}");
                            return true;
                        }
                        else
                        {
                            this.sourceUP = String.Format("{0}{1}", this.SiteCookie.Account, this.Password);
                        }
                    }
                    else
                    {
                        WebServlet.Error(this.Context, "登录异常", String.Format("{0}应用引用模式设置错误，请联系管理员", this.Site.Caption, this.SiteCookie.Account));
                        return true;
                    }
                }


            }
            if (String.IsNullOrEmpty(this.SiteCookie.Account) == false && this.Password == null)
            {
                this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(Site.Root, this.SiteCookie.user_id.Value.ToString(), $"{this.SiteCookie.IndexValue ?? 0}"));
                this.sourceUP = String.Format("{0}{1}", this.SiteCookie.Account, this.Password);

            }
            var login = this.Site.Login;
            var autoCheck = false;
            if (String.IsNullOrEmpty(this.SiteCookie.Account) || this.Password == null)
            {
                if (this.SiteCookie.IndexValue > 0)
                {
                    LoginHtml(String.Empty, true);
                    return true;
                }
                switch (this.Site.Site.UserModel ?? Entities.UserModel.Standard)
                {
                    case Entities.UserModel.Standard:

                        if (login.Finish.IsEmpty == false)
                        {
                            LoginHtml(String.Empty, true);
                        }
                        else
                        {
                            this.Context.Redirect(ReplaceRedirect(new StringValue(this.Site.GetHome())).Span.UTF8());

                        }

                        return true;
                    case Entities.UserModel.Checked:

                        this.SiteCookie.Account = user.Name;
                        this.Password = this.ResetPasswork(form, this.Site);
                        if (this.Password == null)
                        {
                            WebServlet.Error(this.Context, "登录异常", String.IsNullOrEmpty(errorMsg) ? String.Format("应用中未检测到{1}账户，请联系{0}应用管理员确认账户", this.Site.Caption, this.SiteCookie.Account) : errorMsg);
                            return true;
                        }
                        autoCheck = true;
                        this.SiteCookie.Model = (this.SiteCookie.Model ?? Entities.AccountModel.Standard) | Entities.AccountModel.Check | Entities.AccountModel.Changed;
                        this.SiteCookie.ChangedTime = 0;

                        break;

                    case Entities.UserModel.Check:

                        switch (apiKey)
                        {
                            case "Input":
                                LoginHtml(String.Empty, true);
                                return true;
                            case "Auto":
                                this.SiteCookie.Account = user.Name;
                                this.Password = this.ResetPasswork(form, this.Site);
                                if (this.Password == null)
                                {
                                    WebServlet.Error(this.Context, "登录异常", String.IsNullOrEmpty(errorMsg) ? String.Format("应用中未发现{1}账户，您可联系{0}应用管理员或使用<a href=\"/UMC.Login/Input\">其他账户</a>登录", this.Site.Caption, this.SiteCookie.Account) : errorMsg);
                                    return true;
                                }
                                autoCheck = true;
                                this.SiteCookie.Model = (this.SiteCookie.Model ?? Entities.AccountModel.Standard) | Entities.AccountModel.Check | Entities.AccountModel.Changed;
                                this.SiteCookie.ChangedTime = 0;
                                break;
                            default:
                                LoginCheckHtml();
                                return true;
                        }
                        break;
                    case Entities.UserModel.Quote:
                        var quoteRoot = this.Site.Site.Account.Substring(1);
                        var home = Data.WebResource.Instance().WebDomain();
                        this.Context.Redirect($"{this.Context.Scheme}://{quoteRoot}{WebServlet.DomainUnion}{home}/UMC.Login?callback={Uri.EscapeDataString(this.Context.Url.AbsoluteUri)}");
                        return true;
                    case Entities.UserModel.Share:
                        if (this.ShareUser() == false)
                        {
                            WebServlet.Error(this.Context, "登录异常", String.Format("{0}采用共享账户，但账户却未设置，请联系管理员", this.Site.Caption));
                            return true;
                        }
                        break;
                }
            }

            if (login.IsLoginHTML && this.Context.Method == HttpMethod.GET && isBody == false)
            {
                LoginHtml(String.Empty, false);
                return true;
            }
            if (login.IsNotCookieClear == false)
            {
                this.Cookies.Clear();// = String.Empty;
                this.cookieSet.Clear();
            }

            var feildConfig = UMC.Data.JSON.Deserialize<Hashtable>(this.SiteCookie.Config) ?? new Hashtable();

            if (this.Context.Query.IsEmpty == false)
            {
                var qs = this.Context.QueryString;
                foreach (var k in qs.Span)
                {
                    if (k.Name.IsEmpty == false && k.Value.IsEmpty == false)
                    {
                        k.Value.Output((b, i, c) => feildConfig[k.Name.Span.UTF8()] = System.Web.HttpUtility.UrlDecodeToBytes(b, i, c).UTF8());

                    }
                }
            }

            NetHttpResponse httpResponse;// = null;

            var isOk = XHR(login, form, feildConfig, String.Empty, out httpResponse);

            if (isBody)
            {
                if (isOk)
                {

                    this.Context.Loger.Info().Write("更新了在").Write(this.Site.Caption).Write(this.SiteCookie.Account).Write("的密码").End();
                }
                Header(httpResponse, true, true);
                this.Context.OutputStream.Write(_CheckBody.Span);//.Output.Write(_CheckBody);
                return true;

            }
        Check:
            if (isOk)
            {
                this.Context.Loger.Info().Write("在").Write(this.Site.Caption).Write("中用").Write(this.SiteCookie.Account).Write("的账户登录了").End();

                return LoginAfter(feildConfig, form, isHome, httpResponse);
            }
            else
            {
                bool isShowUser = String.IsNullOrEmpty(this.sourceUP);
                if (httpResponse != null)
                {
                    isShowUser = true;
                    if (String.IsNullOrEmpty(errorMsg))
                    {
                        errorMsg = "账户或密码不正确";

                        foreach (var fd in this.Site.Login.Feilds)
                        {
                            if (fd.Finish.IsEmpty == false)
                            {
                                if (this.CheckRes(fd.Finish, httpResponse, _CheckBody))
                                {
                                    isShowUser = String.IsNullOrEmpty(this.sourceUP);
                                    if (fd.RetryCount > 0 && this.RetryCount < fd.RetryCount)
                                    {
                                        this.RetryCount++;
                                        isOk = XHR(login, form, feildConfig, String.Empty, out httpResponse);
                                        goto Check;
                                    }
                                    errorMsg = $"{fd.Caption}不正确";
                                    break;
                                }
                            }
                        }


                    }
                }
                if (this.SiteCookie.IndexValue != 0)
                {
                    LoginHtml(errorMsg, isShowUser);
                    return true;
                }
                else
                {
                    switch (this.Site.Site.UserModel ?? Entities.UserModel.Standard)
                    {
                        case Entities.UserModel.Standard:

                            LoginHtml(errorMsg, isShowUser);
                            return true;
                        case Entities.UserModel.Checked:

                            if (autoCheck)
                            {
                                WebServlet.Error(this.Context, "登录异常", String.IsNullOrEmpty(errorMsg) ? String.Format("在{0}应用{1}检测账户登录失败，您可联系管理员重置标准账户", this.Site.Caption, user.Name) : errorMsg);
                                return true;
                            }
                            else
                            {
                                this.Password = this.ResetPasswork(form, this.Site);


                                if (this.Password == null)
                                {
                                    WebServlet.Error(this.Context, "登录异常", String.IsNullOrEmpty(errorMsg) ? String.Format("在{0}应用{1}检测账户登录失败，您可联系管理员重置标准账户", this.Site.Caption, user.Name) : errorMsg);
                                    return true;
                                }
                                else
                                {
                                    this.SiteCookie.Account = user.Name;

                                    this.SiteCookie.Model = (this.SiteCookie.Model ?? Entities.AccountModel.Standard) | Entities.AccountModel.Check | Entities.AccountModel.Changed; ;
                                    this.SiteCookie.ChangedTime = 0;

                                    feildConfig = UMC.Data.JSON.Deserialize<Hashtable>(this.SiteCookie.Config) ?? new Hashtable();

                                    if (XHR(login, form, feildConfig, String.Empty, out httpResponse))
                                    {

                                        this.Context.Loger.Info().Write("在").Write(this.Site.Caption).Write("中用").Write(this.SiteCookie.Account).Write("账户的重置密码方式登录了").End();
                                        return LoginAfter(feildConfig, form, isHome, httpResponse);
                                    }
                                    else
                                    {
                                        WebServlet.Error(this.Context, this.Site.Site, "登录异常", String.Format("{0}是采用检测密码账户，却不能正常使用，请联系管理员", this.Site.Caption, this.Site.Site.Account.Substring(1)));
                                        return true;
                                    }
                                }
                            }
                        case Entities.UserModel.Check:

                            var am = this.SiteCookie.Model ?? Entities.AccountModel.Standard;
                            if ((am & Entities.AccountModel.Check) == Entities.AccountModel.Check)
                            {
                                goto case Entities.UserModel.Checked;
                            }
                            else
                            {
                                DataFactory.Instance().Delete(this.SiteCookie);
                                LoginCheckHtml();
                                return true;
                            }

                        case Entities.UserModel.Quote:
                            var currentTime = UMC.Data.Utility.TimeSpan();
                            var q = UMC.Data.Utility.IntParse(this.Context.Token.Get("DeviceQuote") as string, 0);
                            if (q + 10 > currentTime)
                            {
                                WebServlet.Error(this.Context, this.Site.Site, "登录异常", String.Format("{0}是引用账户，多次尝试却没有成功，请联系管理员", this.Site.Caption, this.Site.Site.Account.Substring(1)));
                                return true;
                            }
                            else if (isShowUser)
                            {
                                var quoteRoot = this.Site.Site.Account.Substring(1);
                                this.Context.Token.Put("DeviceQuote", currentTime.ToString()).Commit(Context.UserHostAddress, Context.Server);
                                var home = Data.WebResource.Instance().WebDomain();
                                this.Context.Redirect($"{this.Context.Scheme}://{quoteRoot}{WebServlet.DomainUnion}{home}/UMC.Login?callback={Uri.EscapeDataString(this.Context.Url.AbsoluteUri)}");

                            }
                            else
                            {
                                LoginHtml(errorMsg, false);
                            }
                            return true;
                        case Entities.UserModel.Share:
                            LoginHtml(errorMsg, isShowUser);
                            return true;
                        default:
                            LoginHtml(errorMsg, isShowUser);
                            return true;
                    }



                }
            }
        }
        public bool ShareUser()
        {
            var user = this.Site.Site.Account;
            if (String.IsNullOrEmpty(user) == false)
            {

                var vindex = user.IndexOf("~");
                if (vindex > -1)
                {
                    var nv = user.Substring(0, vindex);
                    var fv = user.Substring(vindex + 1);
                    int start = UMC.Data.Utility.IntParse(nv.Substring(nv.Length - fv.Length), -1);
                    int end = UMC.Data.Utility.IntParse(fv, 0);

                    var index = "0000000" + (start + (Data.Reflection.TimeSpanMilli(DateTime.Now) % (end - start + 1)));
                    this.SiteCookie.Account = nv.Substring(0, nv.Length - fv.Length) + index.Substring(index.Length - fv.Length);
                    this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(this.Site.Root, this.Site.Site.Account));
                    return true;
                }
                else if (user.IndexOf('|') > 0)
                {
                    var us = user.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                    this.SiteCookie.Account = us[Data.Reflection.TimeSpanMilli(DateTime.Now) % us.Length];
                    this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(this.Site.Root, this.Site.Site.Account));
                    return true;
                }
                else
                {
                    this.SiteCookie.Account = user;
                    this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(this.Site.Root, this.Site.Site.Account));
                    return true;
                }
            }
            return false;
        }

        bool LoginAfter(Hashtable fieldConfig, HeadValues form, bool isHome, NetHttpResponse httpResponse)
        {
            this.IsChangeUser = true;
            var configValue = new Hashtable();
            var fdcem = fieldConfig.GetEnumerator();
            while (fdcem.MoveNext())
            {
                if (fdcem.Key.ToString().StartsWith("_") == false)
                {
                    configValue[fdcem.Key] = fdcem.Value;
                }
            }

            switch (this.Site.Site.UserModel)
            {
                case Entities.UserModel.Share:
                    break;
                default:
                    if (this.Site.Site.IsAuth == true)
                    {
                        var user = this.User;
                        if (String.Equals(this.SiteCookie.Account, user.Name) || String.IsNullOrEmpty(this.SiteCookie.Account))
                        {
                            configValue["__ORGA"] = user.Organizes;
                            configValue["__ROLE"] = String.Join(",", UMC.Data.DataFactory.Instance().Roles(user.Id.Value, this.Site.Site.SiteKey.Value));//.Join(",");
                        }
                        else
                        {
                            var account = Security.Membership.Instance().Identity(this.Site.Site.SiteKey.Value, this.SiteCookie.Account);
                            if (account != null)
                            {
                                configValue["__ALIAS"] = account.Alias;
                                configValue["__ROLE"] = String.Join(",", account.Roles);
                                configValue["__ORGA"] = String.Join(",", account.Organizes);
                            }
                        }

                    }
                    break;
            }
            this.SiteCookie.Config = UMC.Data.JSON.Serialize(configValue);

            if (this.Site.Login.IsLoginHTML)
            {
                var script = this.Site.Login.Script;
                if (String.IsNullOrEmpty(script) == false && String.Equals(script, "none", StringComparison.CurrentCultureIgnoreCase) == false)
                {
                    var values = this.GetKeyValue(_CheckBody, script);
                    var nvs = (values as Hashtable).GetEnumerator();

                    while (nvs.MoveNext())
                    {
                        fieldConfig[nvs.Key] = nvs.Value;
                    }
                }

            }


            switch (this.Site.Site.UserModel ?? Entities.UserModel.Standard)
            {
                case Entities.UserModel.Check:
                case Entities.UserModel.Checked:
                case Entities.UserModel.Standard:
                    var AccountModel = this.SiteCookie.Model ?? Entities.AccountModel.Standard;

                    var changeTime = (this.SiteCookie.ChangedTime ?? 0) + 3600 * 24 * 100;

                    if (String.Equals(form.Get("AutoUpdatePwd"), "YES"))
                    {

                        this.Update(fieldConfig, form);
                    }
                    else if ((AccountModel.HasFlag(Entities.AccountModel.Changed) || String.Equals(this.Site.Update.UpdateModel, "Compel")) && changeTime < UMC.Data.Utility.TimeSpan())
                    {
                        this.Update(fieldConfig, form);

                    }
                    break;

            }
            if ("/UMC.Login/New"u8.SequenceEqual(this.RawUrl.Span))//, this.RawUrl))
            {
                this.Context.AddHeader(StringValue.CacheControl, "no-store");
                this.Context.ContentType = StringValue.ContentTypeHtml;//"text/html; charset=UTF-8";
                this.Context.Output.WriteLine("<script>window.top.postMessage(JSON.stringify({ type: 'msg', value: '设置多账户成功，现在你可以打开了' }), '*');");
                this.Context.Output.WriteLine("window.top.postMessage(JSON.stringify({ type: 'close', value: 'close' }), '*');</script>");
                return true;
            }

            if (CheckBrowser() == false)
            {
                return true;

            }
            if (this.Site.Login.LoginAfter != null)
            {
                GetConfig(this.Site.Login.LoginAfter, this.Match(fieldConfig, this.SiteCookie.Account, this.Password, ""));
            }

            foreach (var o in this.OuterCookies.Span)
            {
                this.Context.AddHeader(StringValue.SetCookie, this.RemoveDomain(o.Item2));//Utility.FirstReplace(o.Span.UTF8(), h, a));
            }
            var callbackKey = this.Site.Login.Callback ?? "callback";
            var callback = this.Context.QueryString.Get(callbackKey);
            if (String.IsNullOrEmpty(callback) == false)
            {
                this.Context.Redirect(callback);
                return true;
            }


            if (this.Site.Login.IsLoginHTML)
            {
                var mainKey = String.Format("SITE_MIME_{0}_LOGIN_HTML", this.Site.Root).ToUpper();
                var config = UMC.Data.DataFactory.Instance().Config(mainKey)?.ConfValue?.UTF8();
                if (!String.IsNullOrEmpty(config) && String.Equals(config, "none") == false)
                {
                    this.Isurlencoded = false;
                    this.Context.AddHeader(StringValue.CacheControl, "no-store");
                    this.Context.ContentType = StringValue.ContentTypeHtml; ;//"text/html; charset=UTF-8";

                    using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                   .GetManifestResourceStream("UMC.ITME.Resources.login-html.html"))
                    {
                        var str = new System.IO.StreamReader(stream).ReadToEnd();
                        var matchEvaluator = Match(fieldConfig, "");
                        this.Context.Output.Write(new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                        {
                            var key = g.Groups["key"].Value.ToLower();
                            switch (key)
                            {
                                case "title":
                                    return String.Format("{0}账户对接", this.Site.Caption);
                                case "html":
                                    return Regex.Replace(config, matchEvaluator);

                            }
                            return "";

                        }));

                    }
                    return true;
                }
            }

            if (isHome)
            {
                if (_LoginRedirectLocation.IsEmpty == false)
                {
                    if (IsLoginPath(this.Site, _LoginRedirectLocation))
                    {
                        this.Context.Redirect(this.Site.GetHome());
                    }
                    else
                    {
                        this.Context.Redirect(ReplaceRedirect(_LoginRedirectLocation).Span.UTF8());
                    }
                }
                else
                {
                    this.Context.Redirect(this.Site.GetHome());
                }

            }
            return isHome;

        }
        internal void SaveCookie()
        {
            if (this.domainCookie.IsChange)
            {

                DataFactory.Instance().Put(new Entities.Cookie
                {
                    Domain = $"{this.Site.Root}_Main",
                    Time = DateTime.Now,
                    user_id = this.SiteCookie.user_id,
                    CookieValue = this.domainCookie.ToBytes(),
                    IndexValue = this.SiteCookie.IndexValue

                });
            }
            var isSaveCookies = false;
            if (this.cookieSet.IsChange)
            {
                isSaveCookies = true;
                this.SiteCookie.CookieValue = this.cookieSet.ToBytes();
            }

            if (this.IsChangeUser == true)
            {
                var siteCookie = new Entities.Cookie
                {
                    Domain = this.SiteCookie.Domain,
                    Time = DateTime.Now,
                    user_id = this.SiteCookie.user_id,
                    IndexValue = this.SiteCookie.IndexValue

                };


                var nUP = String.Format("{0}{1}", this.SiteCookie.Account, this.Password);

                if (String.Equals(nUP, this.sourceUP) == false)
                {
                    switch (this.Site.Site.UserModel)
                    {
                        case Entities.UserModel.Quote:

                            if (this.SiteCookie.IndexValue > 0)
                            {
                                UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(Site.Root, siteCookie.user_id.Value.ToString(), $"{siteCookie.IndexValue ?? 0}"), this.Password);
                            }
                            break;
                        default:
                            UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(Site.Root, siteCookie.user_id.Value.ToString(), $"{siteCookie.IndexValue ?? 0}"), this.Password);

                            break;
                    }
                    siteCookie.Account = this.SiteCookie.Account;
                    siteCookie.ChangedTime = UMC.Data.Utility.TimeSpan();
                    siteCookie.Model = this.SiteCookie.Model;
                    this.sourceUP = nUP;
                }

                siteCookie.Config = this.SiteCookie.Config;
                siteCookie.CookieValue = this.SiteCookie.CookieValue;
                siteCookie.LoginTime = UMC.Data.Utility.TimeSpan();
                this.IsChangeUser = null;
                DataFactory.Instance().Put(siteCookie);

            }
            else if (isSaveCookies)
            {
                DataFactory.Instance().Put(new Entities.Cookie
                {
                    Domain = this.SiteCookie.Domain,
                    Time = DateTime.Now,
                    user_id = this.SiteCookie.user_id,
                    CookieValue = this.SiteCookie.CookieValue,
                    IndexValue = this.SiteCookie.IndexValue

                });
            }

        }
        void Header(NetHttpResponse httpResponse, bool isContentEncoding, bool isCache)
        {
            var m_HttpHeaders = httpResponse.Headers.Span;
            var statusCode = Convert.ToInt32(httpResponse.StatusCode);
            this.Context.StatusCode = statusCode;
            var headerCheck = new SiteConfig.PageConfig<SiteConfig.ReplaceSetting> { EndPath = StringValue.Empty };

            headerCheck.StartPath = new StringValue("Redirect");
            SiteConfig.PageConfig<SiteConfig.ReplaceSetting> _Redirect;

            this.Site.HostPage.TryGetValue(headerCheck, out _Redirect);

            for (var i = 0; i < m_HttpHeaders.Length; i++)
            {
                var hv = m_HttpHeaders[i];
                switch (hv.HeadKey)
                {
                    case MimeHeadKey.SetCookie:
                        SetCookie(hv);
                        break;
                    case MimeHeadKey.ContentEncoding:
                        if (isContentEncoding)
                        {
                            this.Context.AddHeader(hv);
                        }
                        break;
                    case MimeHeadKey.AccessControlAllowOrigin:
                        if (this.Context.Headers.TryGet("Origin"u8, out var Referer) && Referer.Value.IsEmpty == false)
                        {
                            this.Context.AddHeader(hv.Name, Referer.Value);
                        }
                        else
                        {
                            this.Context.AddHeader(hv.Name, "*");
                        }

                        break;
                    case MimeHeadKey.ContentSecurityPolicyReportOnly:
                    case MimeHeadKey.ContentSecurityPolicy:
                    case MimeHeadKey.Link:
                    case MimeHeadKey.Location:
                        this.Context.AddHeader(hv.Name, this.OutputReplace(hv.Value, _Redirect?.Value));
                        break;
                    case MimeHeadKey.ItmeAccessToken:
                        if (this.Site.Site.UserModel == Entities.UserModel.Bridge)
                        {
                            var access = hv.Value.Span;//.UTF8();
                            if (this.SiteCookie.CookieValue == null || access.SequenceEqual(this.SiteCookie.CookieValue) == false)
                            {
                                this.SiteCookie.CookieValue = access.ToArray();

                                DataFactory.Instance().Put(new Entities.Cookie
                                {
                                    Domain = this.SiteCookie.Domain,
                                    Time = DateTime.Now,
                                    user_id = this.SiteCookie.user_id,
                                    CookieValue = this.SiteCookie.CookieValue,
                                    IndexValue = this.SiteCookie.IndexValue

                                });
                            }
                        }
                        else
                        {
                            goto default;
                        }
                        break;
                    case MimeHeadKey.StrictTransportSecurity:
                    case MimeHeadKey.ContentType:
                    case MimeHeadKey.Server:
                    case MimeHeadKey.Connection:
                    case MimeHeadKey.KeepAlive:
                    case MimeHeadKey.AltSvc:
                        break;
                    case MimeHeadKey.ContentLength:
                    case MimeHeadKey.TransferEncoding:
                        if (httpResponse.IsHead)
                        {
                            this.Context.AddHeader(hv);
                        }
                        break;
                    case MimeHeadKey.LastModified:
                    case MimeHeadKey.ETag:
                        if (isCache)
                        {
                            this.Context.AddHeader(hv);
                        }
                        break;
                    default:
                        headerCheck.StartPath = hv.Name;//  hv.Name;
                        if (this.Site.HostPage.TryGetValue(headerCheck, out var check))
                        {
                            this.Context.AddHeader(hv.Name, this.OutputReplace(hv.Value, check.Value));
                        }
                        else
                        {
                            this.Context.AddHeader(hv);
                        }
                        break;
                }
            }
            foreach (var o in this.OuterCookies.Span)
            {
                this.Context.AddHeader(StringValue.SetCookie, this.RemoveDomain(o.Item2));
            }
            var ContentType = httpResponse.ContentType;

            if (ContentType.IsEmpty == false)
            {
                this.Context.ContentType = ContentType;
            }
            else if (httpResponse.StatusCode == HttpStatusCode.OK)
            {
                this.Context.ContentType = this.Site.ContentType;
            }

        }
        void DoResponse(NetHttpResponse httpResponse)
        {

            var ct = httpResponse.ContentType.Span;
            Encoding encoding = Encoding.UTF8;
            var tIndex = ct.IndexOf("charset="u8, true);
            if (tIndex > 0)
            {
                try
                {
                    var tsp = ct.Slice(tIndex + 8).UTF8().Trim();
                    encoding = Encoding.GetEncoding(tsp);
                }
                catch
                {
                    httpResponse.Transfer(this.Context);
                    return;
                }
            }
            var ms = new System.IO.MemoryStream();
            httpResponse.ReadAsData((b, i, c) =>
            {
                if (c == 0 && b.Length == 0)
                {
                    if (i == -1)
                    {
                        ms.Close();
                        ms.Dispose();
                        this.Context.Error(httpResponse.Error);
                    }
                    else
                    {
                        ms.Flush();
                        ms.Position = 0;
                        try
                        {
                            var file = this.Site.ResBlockPage[Context.Path];

                            switch (file.Type)
                            {
                                case SiteConfig.BlockType.Url:
                                    var webr = new Uri(file.Value).WebRequest();
                                    webr.ContentType = httpResponse.ContentType;
                                    webr.Put(ms, r =>
                                    {
                                        r.Transfer(this.Context);
                                    });
                                    return;
                                case SiteConfig.BlockType.Nodejs:
                                    {

                                        var buffers = ms.GetBuffer().AsSpan(0, (int)ms.Length);

                                        Header(httpResponse, false, true);
                                        string nodeJsScriptPath = Data.Reflection.ConfigPath($"Static/Nodes/{file.Value}.js");
                                        if (File.Exists(nodeJsScriptPath))
                                        {
                                            var stdout = GetNode(nodeJsScriptPath, Convert.ToBase64String(buffers));
                                            if (String.IsNullOrEmpty(stdout))
                                            {
                                                this.Context.OutputStream.Write(encoding.GetBytes($"{file.Value}.js输出为空"));
                                            }
                                            else
                                            {
                                                this.Context.OutputStream.Write(encoding.GetBytes(stdout));
                                            }
                                        }
                                        else
                                        {
                                            this.Context.ContentLength = buffers.Length;
                                            this.Context.OutputStream.Write(buffers);
                                        }
                                    }
                                    break;
                                case SiteConfig.BlockType.Redirect:
                                    {

                                        var buffers = ms.GetBuffer().AsSpan(0, (int)ms.Length);
                                        if (buffers.Contains(encoding.GetBytes(file.Content)))
                                        {
                                            this.Context.Redirect(file.Value);
                                        }
                                        else
                                        {
                                            Header(httpResponse, false, true);
                                            this.Context.ContentLength = buffers.Length;
                                            this.Context.OutputStream.Write(buffers);
                                        }
                                    }
                                    break;
                                case SiteConfig.BlockType.Login:
                                    {

                                        var buffers = ms.GetBuffer().AsSpan(0, (int)ms.Length);
                                        if (buffers.Contains(encoding.GetBytes(file.Content)))
                                        {
                                            this.Context.Redirect("/UMC.Login/Go");
                                        }
                                        else
                                        {
                                            Header(httpResponse, false, true);
                                            this.Context.ContentLength = buffers.Length;
                                            this.Context.OutputStream.Write(buffers);
                                        }
                                    }
                                    break;
                            }
                            this.Context.OutputFinish();
                        }
                        catch (Exception ex)
                        {
                            ms.Close();
                            ms.Dispose();
                            this.Context.Error(ex);
                        }
                    }
                }
                else
                {
                    ms.Write(b, i, c);
                }
            });


        }

        StringValue RemoveDomain(StringValue stringValue)
        {
            var oDest = stringValue.Span;
            int domainIndex = oDest.IndexOf("; Domain="u8, true);
            if (domainIndex > 0)
            {
                int v = oDest.IndexOf(";"u8, false, domainIndex + 1);
                if (this.Site.IsUnion)
                {
                    var host = this.Domain.Host.UTF8().AsSpan();
                    var domain = v > 0 ? stringValue.Slice(domainIndex + 9, v - domainIndex - 9) : stringValue.Slice(domainIndex + 9);
                    if (host.SequenceEqual(domain.Span) == false && host.EndsWith(domain.Span))
                    {
                        var reDomain = WebServlet.MainDomainValue;
                        if (WebServlet.DomainUnion == '-')
                        {
                            reDomain = reDomain.Slice(reDomain.Span.IndexOf((byte)'.'));

                        }

                        var by = new byte[stringValue.Length - domain.Length + reDomain.Length];

                        stringValue.Slice(0, domainIndex + 9).Span.CopyTo(by);
                        reDomain.Span.CopyTo(by.AsSpan(domainIndex + 9));
                        if (v > 0)
                        {
                            stringValue.Slice(v).Span.CopyTo(by.AsSpan(domainIndex + 9 + reDomain.Length));
                        }
                        return new StringValue(by);
                    }
                }

                if (v > 0)
                {
                    var by = new byte[stringValue.Length - (v - domainIndex)];
                    stringValue.Slice(0, domainIndex).Span.CopyTo(by);
                    stringValue.Slice(v).Span.CopyTo(by.AsSpan(domainIndex));
                    return new StringValue(by);
                }
                else
                {
                    return stringValue.Slice(0, domainIndex);
                }

            }
            return stringValue;
        }
        public void Response(NetHttpResponse httpResponse)
        {
            if (httpResponse.Error != null)
            {
                if (DataFactory.Instance().RemoveWeight(this.Domain.Authority) > 0)
                {
                    this.Context.Loger.Warn().Write($"从负载中移除了{this.Domain.Authority}");
                }
                this.Context.Loger.Error().Write(httpResponse.Error?.Message);
            }

            if (httpResponse.IsHead)
            {
                Header(httpResponse, true, true);
            }
            else
            {
                var ctype = httpResponse.ContentType.Slice(";"u8);
                SiteConfig.ReplaceSetting replaceSetting = null;
                StringValue jsAppendKey = StringValue.Empty;
                int model = 0;
                var isHtml = false;
                if (ctype.IsEmpty == false)
                {

                    if (this.Site.ResBlockPage.Contains(Context.Path))
                    {
                        model = -1;
                    }
                    else
                    {
                        isHtml = ctype.Span.SequenceEqual("text/html"u8);

                        if (this.CheckPath(this.Context.Path.Span, ctype, out var _replaceSetting))
                        {
                            if (_replaceSetting.Model.HasFlag(SiteConfig.HostReplaceModel.Replace))
                            {
                                replaceSetting = _replaceSetting;
                                model = 2;
                            }
                        }
                        if (CheckPath(this.Context.Path.Span, out jsAppendKey, this.Site.AppendJSConf) && model == 0)
                        {
                            model = 1;
                        }
                    }

                }
                switch (model)
                {
                    case -1:
                        DoResponse(httpResponse);

                        return;
                    case 1:
                        Header(httpResponse, false, true);
                        if (isHtml)
                        {
                            this.OuterHTML(httpResponse, this.Context.OutputStream, true, jsAppendKey);
                        }
                        else
                        {
                            this.OutputAppendJS(httpResponse, jsAppendKey, this.Context.OutputStream);
                        }
                        return;
                    case 2:
                        Header(httpResponse, false, true);
                        if (isHtml)
                        {
                            this.OuterHTML(httpResponse, replaceSetting, this.Context.OutputStream, true, jsAppendKey);

                        }
                        else
                        {
                            this.OuterReplaceHost(httpResponse, replaceSetting, this.Context.OutputStream, true, jsAppendKey);

                        }
                        return;
                }
            }


            Header(httpResponse, true, true);
            if (httpResponse.ContentLength > -1)
            {
                this.Context.ContentLength = httpResponse.ContentLength;

            }

            httpResponse.ReadAsData((b, i, c) =>
            {
                if (c == 0 && b.Length == 0)
                {
                    if (i == -1)
                    {
                        this.Context.Error(httpResponse.Error);
                    }
                    else
                    {
                        this.Context.OutputFinish();
                    }
                }
                else
                {
                    this.Context.OutputStream.Write(b, i, c);
                }
            });


        }
        UMC.Security.Identity User;

        public void AuthBridge()
        {
            AuthBridge(this.Context.Headers);
        }
        internal void AuthBridge(HeadValues heaers)
        {

            var user = this.User;
            switch (this.Site.Site.UserModel)
            {
                case Entities.UserModel.Share:
                    break;
                default:
                    if (this.Site.Site.IsAuth == true)
                    {
                        user = this.Account;
                    }
                    break;
                case Entities.UserModel.Bridge:
                    if (this.Site.Site.IsAuth == true)
                    {
                        user = this.Account;
                    }
                    if (this.SiteCookie.CookieValue?.Length > 0)
                    {
                        heaers.Add(new HeadValue(new StringValue("itme-access-token"), new StringValue(this.SiteCookie.CookieValue)));
                    }
                    break;
            }
            heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserName, Uri.EscapeDataString(user.Name)));
            heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserId, UMC.Data.Utility.Guid(user.Id.Value)));

            if (String.IsNullOrEmpty(user.Alias) == false)
            {
                heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserAlias, Uri.EscapeDataString(user.Alias)));
            }
            if (user.Roles.Length > 0)
            {
                heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserRoles, Uri.EscapeDataString(String.Join(",", user.Roles))));
            }

            if (user.Organizes.Length > 0)
            {
                heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserOrganizes, Uri.EscapeDataString(String.Join(",", user.Organizes))));
            }

            if (String.IsNullOrEmpty(Site.Site.AppSecret) == false)
            {
                heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserTime, Utility.TimeSpan().ToString()));
                heaers.Add(new HeadValue(UMC.ITME.Utility.UmcRequestUserSign, Utility.Sign(heaers, "umc-"u8, Site.Site.AppSecret)));
            }

        }

        public void LoginRequest()
        {
            this.Context.UseSynchronousIO();
            this.Context.ReadAsForm(this.LoginEnd);
        }
        void ClearCookie(StringValue domain)
        {
            var cCookes = this.Site.OutputCookies;

            if (cCookes.Count > 0)
            {
                var em = cCookes.Span.GetEnumerator();
                while (em.MoveNext())
                {
                    var cookie = em.Current;
                    if (cookie.Domain.Span.SequenceEqual("*"u8))
                    {
                        this.Context.Cookies.Remove(cookie.Name.Span);
                        int l = Context.Host.Span.IndexOf(HttpReplacer.BytePOINT);
                        if (l > 0)
                        {
                            this.Context.AddHeader(StringValue.SetCookie, this.Context.Memory.Rent($"{cookie.Name}=; Expires={DateTime.Now.AddYears(-1):r}; HttpOnly; Path={cookie.Path}; Domain={Context.Host.Slice(l)}"));
                        }
                    }
                    else if (domain.Span.SequenceEqual(cookie.Domain.Span))
                    {
                        this.Context.Cookies.Remove(cookie.Name.Span);
                        this.Context.AddHeader(StringValue.SetCookie, this.Context.Memory.Rent($"{cookie.Name}=; Expires={DateTime.Now.AddYears(-1):r}; HttpOnly; Path={cookie.Path}"));
                    }
                }
            }
            this.cookieSet.Clear();
        }
        void LoginEnd(HeadValues form)
        {
            try
            {
                Login(form);
            }
            finally
            {
                this.Context.OutputFinish();
            }
        }
        void Login(HeadValues form)
        {

            var apis = this.Context.Url.AbsolutePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            if (apis.Length == 1)
            {
                this.Context.AddHeader(StringValue.SetCookie, $"{DeviceIndex}=; Expires={DateTime.Now.AddDays(-10):r}; HttpOnly; Path=/");

                foreach (var k in this.OuterCookies.Span)
                {
                    this.Context.AddHeader(new HeadValue(StringValue.SetCookie, this.RemoveDomain(k.Item2)));
                }
                if (this.Site.Site.UserModel == Entities.UserModel.Bridge)
                {
                    this.Context.Redirect(this.Site.GetHome());
                }
                else if (CheckAccountSelectHtml() == false)
                {
                    if (this.Site.IsGotoMain)
                    {
                        this.Context.Redirect(ReplaceRedirect(new StringValue(this.Site.GetHome())).Span.UTF8());
                    }
                    else
                    {
                        if (this.Site.IsForwardProxy)
                        {
                            var ustName = this.Context.Token.Username ?? String.Empty;
                            var buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(712);
                            var size = ustName.WriteBytes(buffer, 0);
                            WebServlet.AppId.Span.CopyTo(buffer.AsSpan(size));
                            size += 16;
                            WebServlet.AppSecret.Span.CopyTo(buffer.AsSpan(size));
                            size += 16;
                            BitConverter.TryWriteBytes(buffer.AsSpan(size), Utility.TimeSpan());
                            size += 4;
                            var sign = buffer.AsSpan(size, 16);
                            Utility.MD5(buffer.AsSpan(0, size), buffer.AsSpan(size, 16));


                            var ms = HotCache.Find(new ProxySite());
                            var rootSpan = Site.Site.SiteKey.Value.StringValue().Span;

                            var indexs = new HashSet<uint>
                            {
                                0
                            };
                            foreach (var m in ms)
                            {
                                indexs.Add(m.ProxyIP.UInt32() ?? 0);
                            }
                            var proxys = indexs.ToArray();
                            
                            Array.Sort(proxys);

                            var outIndex = new HashSet<int>();

                            foreach (var m in ms)
                            {
                                var index = m.ProxyIP.UInt32() ?? 0;

                                int v = Array.BinarySearch(proxys, index);
                                if (v > -1)
                                {
                                    if (m.ConfigKey.Span.Contains(rootSpan))
                                    {
                                        outIndex.Add(v);
                                    }
                                }
                            }


                            var url = $"/{WebServlet.AppIdKey}/{ustName}/{Utility.ToBase64String(buffer.AsSpan(size - 4, 20))}/{WebServlet.AuthDomain(this.Context).Host}";
                            var sb = new StringBuilder();
                            sb.Append("<div class=\"app-loading-title\">");
                            sb.Append(this.Site.Caption);
                            sb.Append("</div></div></div><script auth=\"https://proxy.apiumc.com");
                            sb.Append(url);
                            sb.Append("\" path=\"");
                            sb.Append(url);
                            sb.Append("\" proxy=\"");
                            var inds = outIndex.ToArray();

                            size = ustName.WriteBytes(buffer, 0);
                            BitConverter.TryWriteBytes(buffer.AsSpan(size), Utility.IntParse(WebServlet.AppId.Span));


                            var key = UMC.Security.Base32Encoding.ToString(buffer.AsSpan(0, size + 4)).TrimEnd('=').ToLower();

                            for (var i = 0; i < inds.Length; i++)// in indexs){
                            {
                                if (i > 0)
                                {
                                    sb.Append(',');
                                }
                                sb.Append($"https://{key}-{inds[i]}.proxy.apiumc.com");

                            }
                            sb.Append("\" src=\"/UMC.js/umc.proxy.js\"></script></body></html>");
                            WebServlet.HtmlResource(this.Context, "loading", sb.ToString());

                        }
                        else
                        {
                            this.Context.AddHeader("Refresh", $"0;URL=/UMC.Login/Go{this.Context.Url.Query}");
                            WebServlet.HtmlResource(this.Context, "loading", $"<div class=\"app-loading-title\">{this.Site.Caption}</div></div></div></body></html>");

                        }
                    }
                }
                return;
            }
            var lv = apis[1];

            switch (lv)
            {
                case "Proxy":
                    // if (IPAddress.TryParse(this.Context.UserHostAddress, out var v))
                    // {
                    //     var usString = this.Context.QueryString.Get("userAgent");
                    //     if (String.IsNullOrEmpty(usString) == false)
                    //     {
                    //         var userAgent = new StringValue(Utility.FromBase64String(usString));
                    //         ushort uPort = 443;
                    //         UMC.Bridge.SocksUser.Cache.Put(new Bridge.SocksUser
                    //         {
                    //             ClientIP = new StringValue(v.GetAddressBytes()),
                    //             Port = uPort.StringValue(),
                    //             UserAgent = userAgent.Slice(2),
                    //             Username = new StringValue(this.Context.Token.Username),
                    //             ActiveTime = new StringValue(BitConverter.GetBytes(Utility.TimeSpan())),
                    //             ExpirationTime = new StringValue(BitConverter.GetBytes(Utility.TimeSpan(DateTime.Now.AddHours(1))))
                    //         });
                    //     }
                    // }
                    var home = new Uri(this.Domain, this.Site.GetHome());
                    this.Context.Redirect(home.AbsoluteUri);
                    break;

                case "Out":
                    this.Login(true, true, form, String.Empty);
                    return;
                case "Clear":
                    if (this.Site.IsUnion)
                    {
                        this.domainCookie.Clear();
                        this.domainCookie.IsChange = true;
                        this.cookieSet.Clear();
                        this.cookieSet.IsChange = true;

                        this.ClearCookie(this.PfxDomain);
                        foreach (var o in this.OuterCookies.Span)
                        {
                            this.Context.AddHeader(StringValue.SetCookie, this.RemoveDomain(o.Item2));
                        }
                        this.Context.Redirect("/");
                    }
                    else
                    {
                        this.ClearCookie(StringValue.Empty);
                        this.cookieSet.Clear();
                        this.cookieSet.IsChange = true;
                        foreach (var o in this.OuterCookies.Span)
                        {
                            this.Context.AddHeader(StringValue.SetCookie, this.RemoveDomain(o.Item2));
                        }

                        this.Context.Redirect("/UMC.Login");
                    }
                    return;
                case "Check":
                    if (Site.Site.AuthType >= WebAuthType.User)
                    {
                        if (this.SiteCookie.Time.HasValue)
                        {
                            var authExpire = this.Site.Site.AuthExpire ?? 30;
                            if (authExpire > 0 && this.SiteCookie.Time.Value.AddMinutes(authExpire) < DateTime.Now)
                            {
                                this.Context.Redirect("/UMC.Login/Go" + this.Context.Url.Query);
                            }
                            else
                            {
                                var callback = this.Context.QueryString.Get("callback");
                                if (String.IsNullOrEmpty(callback) == false)
                                {
                                    this.Context.Redirect(callback);
                                }
                                else
                                {
                                    this.Context.Redirect(ReplaceRedirect(new StringValue(this.Site.GetHome())).Span.UTF8());
                                }
                            }
                        }
                        else
                        {
                            this.Context.Redirect("/UMC.Login/Go" + this.Context.Url.Query);
                        }
                    }
                    break;
                case "Auto":
                case "Input":
                case "Go":
                    this.Login(true, false, form, lv);
                    return;
                case "New":
                    var sc = DataFactory.Instance().Cookies(this.Site.Root, User.Id.Value).OrderBy(r => r.IndexValue).FirstOrDefault(r => String.IsNullOrEmpty(r.Account));
                    if (sc != null)
                    {
                        if (sc.IndexValue != this.SiteCookie.IndexValue)
                        {
                            this.SiteCookie = sc;
                            this.Context.AddHeader(StringValue.SetCookie, $"{DeviceIndex}={this.SiteCookie.IndexValue}; HttpOnly; Path=/");
                            this.Cookies.Clear();
                            this.cookieSet.Clear();
                        }
                        this.Login(true, false, form, String.Empty);
                    }
                    return;
                default:
                    if (Utility.IntParse(lv, -1) > -1)
                    {
                        ClearCookie(StringValue.Empty);

                        if (String.Equals(lv, "0") == false)
                        {
                            this.Context.AddHeader(StringValue.SetCookie, $"{DeviceIndex}={lv}; HttpOnly; Path=/");

                        }
                        else
                        {
                            this.Context.AddHeader(StringValue.SetCookie, $"{DeviceIndex}=; Expires={DateTime.Now.AddYears(-10):r}; HttpOnly; Path=/");
                        }

                        foreach (var o in this.OuterCookies.Span)
                        {
                            this.Context.AddHeader(new HeadValue(StringValue.SetCookie, this.RemoveDomain(o.Item2)));
                        }
                        if (this.Site.IsGotoMain)
                        {
                            this.Context.Redirect(ReplaceRedirect(new StringValue(this.Site.GetHome())).Span.UTF8());
                        }
                        else
                        {
                            this.Context.Redirect("/UMC.Login/Go");
                        }
                        return;
                    }
                    break;
            }
            var login = this.Site.Login.Feilds.FirstOrDefault(r => r.Name == lv);
            if (login != null)
            {
                this.Password = UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(this.Site.Root, this.SiteCookie.user_id.Value.ToString(), "0"));
                var hash = new Hashtable();
                UMC.Data.Utility.AppendDictionary(hash, form);
                var usernmae = hash["Username"] as string;
                hash.Remove("Username");
                this.Context.ContentType = StringValue.ContentTypeJson;
                var json = GetConfig(login, this.Match(hash, usernmae ?? this.SiteCookie.Account, this.Password, ""));
                if (String.Equals("[]", json) || String.Equals("{}", json))
                {
                    if (String.IsNullOrEmpty(login.DefautValue) == false)
                    {
                        var sKey = SiteConfig.Config(login.DefautValue);
                        switch (sKey.Length)
                        {
                            case 0:
                                break;
                            case 1:
                                json = UMC.Data.JSON.Serialize(new WebMeta[] { new WebMeta().Put("Text", sKey[0], "Value", sKey[0]) });
                                break;
                            default:
                                var ls = new List<WebMeta>();
                                int l = sKey.Length / 2;
                                for (var i = 0; i < l; i++)
                                {
                                    ls.Add(new WebMeta().Put("Text", sKey[0], "Value", sKey[1]));
                                }
                                json = UMC.Data.JSON.Serialize(ls);

                                break;
                        }

                    }
                }

                this.Context.Output.Write(json);
            }
            else
            {
                var hash = new Hashtable();
                UMC.Data.Utility.AppendDictionary(hash, this.Context.QueryString);
                lv = this.Context.QueryString.Get("$");
                hash.Remove("$");
                if (String.IsNullOrEmpty(lv) == false)
                {
                    this.Isurlencoded = false;
                    this.Context.ContentType = StringValue.ContentTypeJson;
                    this.Context.Output.Write(Regex.Replace(lv, this.Match(hash, "", "", "")));

                }
            }
        }
        string _RootKey;
        public void ProcessRequest()
        {

            if (this.StaticModel != 0 && this.Site.Site.UserModel == Entities.UserModel.Bridge)
            {
                this.AuthBridge();
            }

            this.Context.UseSynchronousIO();
            switch (this.Context.Method)
            {
                case HttpMethod.GET:


                    if (IsLoginPath(this.Site, this.RawUrl, out var ReUrl))
                    {
                        if (ReUrl == "@")
                        {
                            if (this.Login(false, false, new HeadValues(), String.Empty))
                            {
                                this.Context.OutputFinish();
                            }
                            else
                            {
                                Get();
                            }
                        }
                        else if (String.IsNullOrEmpty(ReUrl) == false)
                        {

                            this.Context.Redirect(ReUrl);
                        }

                        else
                        {

                            var urlReferrer = this.Context.UrlReferrer;
                            if (urlReferrer == null || String.Equals(this.Context.Host, urlReferrer.Host) == false)
                            {
                                this.Context.Redirect("/UMC.Login");
                            }
                            else
                            {
                                SignOutHtml();
                            }
                            this.Context.OutputFinish();
                        }
                    }
                    else
                    {
                        Get();
                    }
                    break;
                case HttpMethod.OPTIONS:
                    {
                        var webReq = this.Reqesut(this.Context.Transfer(Domain));
                        webReq.RawUrl = RawUrl;
                        webReq.Net(this.Context, (xhr) =>
                        {
                            xhr.Headers[StringValue.AccessControlAllowCredentials] = new StringValue("true".UTF8());
                            this.Response(xhr);
                        });
                    }
                    break;
                default:
                    {
                        var webReq = this.Reqesut(this.Context.Transfer(Domain));
                        webReq.RawUrl = RawUrl;
                        if (this.CheckPath(Context.Path.Span, out var replaceSetting))
                        {
                            if (replaceSetting.Model.HasFlag(SiteConfig.HostReplaceModel.Input) && (this.Context.ContentLength ?? 0) > 0)
                            {
                                var ms = NetClient.TempStream();
                                var replacer = new HttpReplacer(this, ms.Write, replaceSetting, 0, 2);
                                this.Context.ReadAsData(new UMC.Net.DataReader((b, i, c) =>
                                {
                                    replacer.Replace((buffer, offset, size) =>
                                    {
                                        if (c == 0)
                                        {
                                            return 0;
                                        }
                                        buffer[offset] = b[i];
                                        i++;
                                        c--;
                                        return 1;
                                    });
                                }, e =>
                                {
                                    replacer.Flush();
                                    ms.Flush();
                                    ms.Position = 0;
                                    webReq.ContentType = this.Context.ContentType;
                                    webReq.Net(this.Context.Method, ms, ms.Length, r =>
                                    {
                                        ms.Close();
                                        ms.Dispose();
                                        this.Response(r);
                                    });
                                }, e =>
                                {
                                    this.Context.Error(e ?? new WebException("接收Body错误"));
                                }).Write);
                            }
                            else
                            {
                                webReq.Net(this.Context, this.Response);
                            }
                        }
                        else
                        {
                            webReq.Net(this.Context, this.Response);

                        }
                    }
                    break;
            }
        }
        void Get()
        {
            var IsCache = false;

            string filename = String.Empty;

            if (this.StaticModel >= 0)
            {
                var pmd5Key = $"{this.Site.Site.Version}{_RootKey}{WebServlet.MainDomain}{WebServlet.DomainUnion}";
                switch (this.StaticModel)
                {
                    case 0:
                        break;
                    case 1:
                        break;
                    case 2:
                        pmd5Key = $"{pmd5Key}{this.SiteCookie.Account}";
                        break;
                    default:
                        pmd5Key = String.Format("{0}_{1}_{2}", this.SiteCookie.Account, UMC.Data.Utility.TimeSpan() / 60 / this.StaticModel, pmd5Key);
                        break;
                }
                IsCache = true;
                if (this.Context.CheckCache(Site.Root, pmd5Key, out filename))
                {
                    this.Context.OutputFinish();
                    return;
                }

            }
            var webr = this.Reqesut(Context.Transfer(this.Domain));

            webr.RawUrl = RawUrl;
            webr.Get(httpResponse =>
              {
                  var statusCode = Convert.ToInt32(httpResponse.StatusCode);

                  this.Context.StatusCode = statusCode;
                  var ctype = httpResponse.ContentType;
                  if (httpResponse.Error != null)
                  {
                      if (DataFactory.Instance().RemoveWeight(this.Domain.Authority) > 0)
                      {
                          this.Context.Loger.Warn().Write($"从负载中移除了{this.Domain.Authority}");
                      }
                      this.Context.Loger.Error().Write(httpResponse.Error?.Message);
                  }

                  if (ctype.IsEmpty == false)
                  {
                      this.Context.ContentType = ctype;
                      ctype = ctype.Slice(";"u8);

                      var path = Context.Path.Span;
                      StringValue jsAppendKey = StringValue.Empty;
                      SiteConfig.ReplaceSetting replaceSetting = null;
                      SiteConfig.ImageConfig ImageConfig = null;
                      bool isHtml = false;
                      int model = 0;
                      if (this.Site.ResBlockPage.Contains(Context.Path))
                      {
                          model = -1;
                          IsCache = false;
                      }
                      else if (ctype.Span.StartsWith("image/"u8) && ctype.Contains("svg"u8) == false)
                      {
                          var ckey = Context.QueryString.Get("umc-image"u8);
                          if (ckey.IsEmpty == false)
                          {
                              if (TryImageConf(ckey, out ImageConfig) || TryImageConfig(ckey.Span, this.Site, out ImageConfig))
                              {
                                  if (String.Equals(ImageConfig.Format, "Src") == false)
                                  {
                                      ctype = new StringValue("image/" + ImageConfig.Format);
                                  }
                                  model = 4;
                              }
                          }
                          else if (TryImageConfig(path, ctype.Span, this.Site, out ImageConfig))
                          {
                              if (String.Equals(ImageConfig.Format, "Src") == false)
                              {
                                  ctype = new StringValue("image/" + ImageConfig.Format);
                              }
                              model = 4;

                          }
                      }
                      else
                      {
                          isHtml = ctype.Contains("text/html"u8, true);

                          if (this.CheckPath(path, ctype, out var _replaceSetting))
                          {
                              if (_replaceSetting.Model.HasFlag(SiteConfig.HostReplaceModel.Replace))
                              {
                                  replaceSetting = _replaceSetting;
                                  model = 2;
                              }
                          }
                          if (CheckPath(path, out jsAppendKey, this.Site.AppendJSConf) && model == 0)
                          {
                              model = 1;
                          }
                      }



                      if (IsCache)
                      {
                          if (httpResponse.Headers.Get(StringValue.CacheControl.Span).Span.SequenceEqual("no-store"u8))
                          {
                              IsCache = false;
                          }
                      }
                      else
                      {

                      }
                      if (httpResponse.StatusCode == HttpStatusCode.OK && IsCache)
                      {
                          switch (model)
                          {
                              case 1:
                                  {
                                      var tempFile = System.IO.Path.GetTempFileName();
                                      var etag = Utility.TimeSpan();
                                      var cacheStream = NetClient.MimeStream(tempFile, ctype, etag);

                                      Header(httpResponse, false, false);
                                      this.Context.AddHeader(StringValue.ETag, etag.ToString());
                                      Action close = () =>
                                      {
                                          if (httpResponse.IsHttpFormatError == false)
                                          {

                                              UMC.Data.Utility.Move(tempFile, filename);
                                          }
                                          else
                                          {
                                              DeleteCache(tempFile);
                                          }
                                      };
                                      if (isHtml)
                                      {
                                          this.OuterHTML(httpResponse, new CopyStream(close, cacheStream, this.Context.OutputStream), false, jsAppendKey);
                                      }
                                      else
                                      {
                                          this.OutputAppendJS(httpResponse, jsAppendKey, new CopyStream(close, cacheStream, this.Context.OutputStream));
                                      }
                                  }
                                  break;
                              case 2:
                                  {
                                      var tempFile = System.IO.Path.GetTempFileName();
                                      var etag = Utility.TimeSpan();
                                      var cacheStream = NetClient.MimeStream(tempFile, ctype, etag);
                                      Header(httpResponse, false, false);
                                      this.Context.AddHeader(StringValue.ETag, etag.ToString());
                                      Action close = () =>
                                      {
                                          if (httpResponse.IsHttpFormatError == false)
                                          {

                                              UMC.Data.Utility.Move(tempFile, filename);
                                          }
                                          else
                                          {
                                              DeleteCache(tempFile);
                                          }
                                      };

                                      if (isHtml)
                                      {
                                          this.OuterHTML(httpResponse, replaceSetting, new CopyStream(close, cacheStream, this.Context.OutputStream), false, jsAppendKey);
                                      }
                                      else
                                      {

                                          this.OuterReplaceHost(httpResponse, replaceSetting, new CopyStream(close, cacheStream, this.Context.OutputStream), false, jsAppendKey);
                                      }
                                      break;
                                  }
                              case 4:
                                  {
                                      var tempFile = System.IO.Path.GetTempFileName();
                                      var etag = Utility.TimeSpan();
                                      var cacheStream = NetClient.MimeStream(tempFile, ctype, etag);
                                      Header(httpResponse, false, false);

                                      httpResponse.ReadAsStream(content =>
                                      {
                                          content.Position = 0;
                                          UMC.Data.Utility.Move(tempFile, filename);
                                          SiteImage.Convert(content, cacheStream, ImageConfig, filename);
                                          content.Dispose();
                                          cacheStream.Flush();
                                          cacheStream.Position = 0;
                                          this.Context.OutputCache(cacheStream, filename);
                                          this.Context.OutputFinish();

                                      }, e =>
                                      {
                                          cacheStream.Close();
                                          DeleteCache(tempFile);
                                          this.Context.Error(e);
                                      });
                                  }
                                  break;
                              default:
                                  {

                                      var tempFile = System.IO.Path.GetTempFileName();
                                      var etag = Utility.TimeSpan();
                                      var cacheStream = NetClient.MimeStream(tempFile, ctype, etag);
                                      Header(httpResponse, true, false);
                                      this.Context.AddHeader(StringValue.ETag, etag.ToString());
                                      //   this.Context.AddHeader(StringValue.XCacheKey, etag.ToString());

                                      if (httpResponse.ContentLength > -1)
                                      {
                                          this.Context.ContentLength = httpResponse.ContentLength;
                                      }
                                      var buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(512);

                                      HttpReadBody.ReadBody(this.Context.OutputStream.Write, r =>
                                      {
                                          int len;
                                          while ((len = r.Read(buffer, 0, buffer.Length)) > 0)
                                          {
                                              cacheStream.Write(buffer, 0, len);
                                          }

                                      }, e =>
                                      {
                                          System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
                                          cacheStream.Flush();
                                          cacheStream.Close();
                                          UMC.Data.Utility.Move(tempFile, filename);
                                          this.Context.OutputFinish();

                                      }, () =>
                                      {
                                          System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
                                          DeleteCache(tempFile);
                                          this.Context.Error(httpResponse.Error);
                                      }).Append(httpResponse);
                                  }
                                  break;
                          }
                          return;

                      }
                      else
                      {
                          switch (model)
                          {
                              case -1:

                                  DoResponse(httpResponse);
                                  return;
                              case 4:
                                  Header(httpResponse, false, false);
                                  httpResponse.ReadAsStream(content =>
                                  {
                                      content.Position = 0;
                                      if (ctype.Contains("Optimal"u8, true))
                                      {
                                          this.Context.ContentType = StringValue.ContentTypeImageWebP;
                                      }
                                      SiteImage.Convert(content, this.Context.OutputStream, ImageConfig, String.Empty);

                                      this.Context.OutputFinish();

                                  }, this.Context.Error);
                                  return;
                              case 2:
                                  Header(httpResponse, false, false);
                                  if (isHtml)
                                  {
                                      this.OuterHTML(httpResponse, replaceSetting, this.Context.OutputStream, false, jsAppendKey);
                                  }
                                  else
                                  {

                                      this.OuterReplaceHost(httpResponse, replaceSetting, this.Context.OutputStream, false, jsAppendKey);
                                  }

                                  return;
                              case 1:

                                  Header(httpResponse, false, false);
                                  if (isHtml)
                                  {
                                      this.OuterHTML(httpResponse, this.Context.OutputStream, true, jsAppendKey);
                                  }
                                  else
                                  {
                                      this.OutputAppendJS(httpResponse, jsAppendKey, this.Context.OutputStream);
                                  }

                                  return;

                          }
                      }
                  }
                  else if (httpResponse.StatusCode == HttpStatusCode.OK)
                  {
                      this.Context.ContentType = Site.ContentType;
                  }
                  Header(httpResponse, true, true);
                  if (httpResponse.ContentLength > -1)
                  {
                      this.Context.ContentLength = httpResponse.ContentLength;
                  }
                  httpResponse.ReadAsData((b, i, c) =>
                  {
                      if (c == 0 && b.Length == 0)
                      {
                          if (i == -1)
                          {
                              this.Context.Error(httpResponse.Error);
                          }
                          else
                          {
                              this.Context.OutputFinish();
                          }
                      }
                      else
                      {
                          this.Context.OutputStream.Write(b, i, c);
                      }
                  });
              });

            // if (this.IsLog)
            // {

            //     var netLoger = this.Context.Loger.Debug();
            //     netLoger.Write(this.Context.HttpMethod);
            //     netLoger.Write(":");
            //     netLoger.Write(this.RawUrl.Span);
            //     netLoger.Write(Mime.RowEnd);

            //     HeadValuesLog(netLoger, webr.Headers);
            //     netLoger.End();

            // }

        }
        void HeadValuesLog(NetLoger netLoger, HeadValues headValues)
        {
            foreach (var k in headValues.Span)
            {
                netLoger.Write(k.Name.Span);
                netLoger.Write(":");
                netLoger.Write(k.Value.Span);
                netLoger.Write(Mime.RowEnd);
            }
            netLoger.Write(Mime.RowEnd);
        }
        bool CheckBrowser()
        {
            var uB = Site.Site.UserBrowser ?? Entities.UserBrowser.All;
            var cilentB = Entities.UserBrowser.All;
            var us = this.Context.UserAgent;
            if (uB == Entities.UserBrowser.All)
            {
                return true;

            }
            else if (us.IsEmpty == false)
            {
                if (us.Contains("CHROME"u8, true))
                {
                    cilentB = Entities.UserBrowser.Chrome;
                }
                else if (us.Contains("FIREFOX"u8, true))
                {
                    cilentB = Entities.UserBrowser.Firefox;
                }
                else if (us.Contains("MSIE"u8, true))
                {
                    cilentB = Entities.UserBrowser.IE;
                }
                else if (us.Contains("DINGTALK"u8, true))
                {
                    cilentB = Entities.UserBrowser.Dingtalk;
                }
                else if (us.Contains("WXWORK"u8, true) || us.Contains("MICROMESSENGER"u8, true))
                {
                    cilentB = Entities.UserBrowser.WeiXin;
                }
                else if (us.Contains("WEBKIT"u8, true))
                {
                    cilentB = Entities.UserBrowser.WebKit;
                }
                if ((uB & cilentB) != cilentB)
                {
                    var ts = UMC.Data.Utility.Enum(uB);

                    var sb = new List<String>();
                    foreach (var k in ts)
                    {
                        switch (k)
                        {
                            case Entities.UserBrowser.Chrome:
                                sb.Add("谷歌");
                                break;
                            case Entities.UserBrowser.IE:
                                sb.Add("IE");
                                break;
                            case Entities.UserBrowser.Firefox:
                                sb.Add("火狐");
                                break;
                            case Entities.UserBrowser.WebKit:
                                sb.Add("WebKit");
                                break;
                            case Entities.UserBrowser.Dingtalk:
                                sb.Add("钉钉");
                                break;
                            case Entities.UserBrowser.WeiXin:
                                sb.Add("微信");
                                break;
                        }
                    }

                    this.Context.AddHeader(StringValue.CacheControl, "no-store");
                    this.Context.ContentType = StringValue.ContentTypeHtml;// "text/html; charset=UTF-8";
                    using (System.IO.Stream stream = typeof(HttpProxy).Assembly
                                                          .GetManifestResourceStream("UMC.ITME.Resources.check.html"))
                    {

                        var str = new System.IO.StreamReader(stream).ReadToEnd();
                        this.Context.Output.Write(new System.Text.RegularExpressions.Regex("\\{(?<key>\\w+)\\}").Replace(str, g =>
                        {
                            var key = g.Groups["key"].Value.ToLower();
                            switch (key)
                            {
                                case "authurl":
                                    return new Uri(this.Context.Url, String.Format("/UMC.Auth/{0}/UMC.Login", Utility.MD5(this.Context.Token.Device.Value))).AbsoluteUri;

                                case "authkey":
                                    return "/UMC/Proxy/Auth";

                                case "isie":
                                    return uB == Entities.UserBrowser.IE ? "yes" : "no";

                                case "desc":
                                    return String.Format("{0}只支持在{1}中使用", Site.Caption, String.Join(",", sb.ToArray()));
                            }
                            return "";

                        }));

                    }
                    return false;
                }
            }
            return true;
        }
        static bool IsLoginPath(SiteConfig config, StringValue rawUrl, out String value)
        {
            value = String.Empty;
            foreach (var cPath in config.LogoutPath.Span)
            {
                switch (cPath.Item3)
                {
                    case 2:
                        if (rawUrl.Span.EndsWith(cPath.Item1.Span))
                        {
                            value = cPath.Item2;
                            return true;
                        }
                        break;
                    case 1:
                        if (rawUrl.Span.StartsWith(cPath.Item1.Span))
                        {
                            value = cPath.Item2;
                            return true;
                        }
                        break;
                    default:
                        if (rawUrl.Span.SequenceEqual(cPath.Item1.Span))
                        {
                            value = cPath.Item2;
                            return true;
                        }
                        break;
                }


            }
            return false;
        }
        public static bool IsLoginPath(SiteConfig config, StringValue rawUrl)
        {
            return IsLoginPath(config, rawUrl, out var _);
        }
        public static void DeleteCache(String cacheKey)
        {
            File.Delete(cacheKey);
        }

        public NetHttpRequest Reqesut(NetHttpRequest webr)
        {
            webr.Proxy = this.Site.Proxy;

            if (CheckPath("Redirect"u8, out var replaceSetting))
            {
                if (webr.Headers.TryGet(StringValue.Referer.Span, out var Referer) && Referer.Value.IsEmpty == false)
                {
                    webr.Headers[Referer.Name] = this.Context.Memory.Rent(ReplaceHost(replaceSetting, 0, Referer.Value, 0, 3));

                }
                if (webr.Headers.TryGet(StringValue.Origin.Span, out Referer) && Referer.Value.IsEmpty == false)
                {
                    webr.Headers[Referer.Name] = this.Context.Memory.Rent(ReplaceHost(replaceSetting, 0, Referer.Value, 0, 3));
                }
            }
            if (this.Cookies.Span.Length > 0)
            {
                var cacheValue = this.Context.Memory.Rent(this.Cookies.BytesSize + this.Cookies.Span.Length * 3);
                var size = 0;
                foreach (var ck in this.Cookies.Span)
                {
                    ck.Name.Span.CopyTo(cacheValue.Span.Slice(size));
                    size += ck.Name.Length;
                    cacheValue.Span[size] = 61;
                    size++;
                    ck.Value.Span.CopyTo(cacheValue.Span.Slice(size));
                    size += ck.Value.Length;
                    cacheValue.Span[size] = 59;
                    size++;
                    cacheValue.Span[size] = 32;
                    size++;
                }
                webr.Headers[StringValue.Cookie] = cacheValue.Slice(0, size - 2);
            }
            WebServlet.WebHeaderConf(webr, this.Site, this.Context, this.SiteCookie.Account);

            var host2 = this.Site.Site.Host;
            if (String.IsNullOrEmpty(host2) == false)
            {
                var port = webr.Address.Port;
                if (String.Equals(host2, "*"))
                {
                    webr.Headers[StringValue.Host] = this.Context.Host;
                }
                else
                {
                    switch (port)
                    {
                        case 80:
                        case 443:
                            break;
                        default:
                            host2 = String.Format("{0}:{1}", host2, port);
                            break;
                    }
                    webr.Headers[StringValue.Host] = this.Context.Memory.Rent(host2);
                }
            }

            webr.Timeout = (this.Site.Site.Timeout ?? 10) * 1000;
            return webr;
        }

        bool CheckPath(ReadOnlySpan<byte> path, out SiteConfig.ReplaceSetting replaceSetting)
        {
            replaceSetting = null;
            foreach (var v in this.Site.HostPage.Span)
            {
                if (path.StartsWith(v.StartPath.Span) && path.EndsWith(v.EndPath.Span))
                {
                    replaceSetting = v.Value;
                    return true;
                }
            }
            return false;
        }
        bool CheckPath(ReadOnlySpan<byte> path, StringValue ctype, out SiteConfig.ReplaceSetting replaceSetting)
        {
            replaceSetting = null;

            foreach (var v in this.Site.HostPage.Span)
            {
                if (replaceSetting == null)
                {
                    if (v.EndPath.IsEmpty && ctype.Span.SequenceEqual(v.StartPath.Span))//, v.StartPath))
                    {
                        replaceSetting = v.Value;
                        continue;
                    }
                }
                if (path.StartsWith(v.StartPath.Span) && path.EndsWith(v.EndPath.Span))
                {
                    replaceSetting = v.Value;
                    return true;
                }
            }

            return replaceSetting != null;
        }
        internal static bool CheckPath(ReadOnlySpan<byte> path, StringValue ctype, out StringValue key, SiteConfig.PageConfig<StringValue>[] cfs)
        {
            var type = ctype.Span;
            key = StringValue.Empty;
            foreach (var d in cfs)
            {
                var span = d.Value.Span;
                if (key.IsEmpty && span.SequenceEqual(type))
                {
                    key = ctype;
                    continue;
                }
                if (path.StartsWith(d.StartPath.Span) && path.EndsWith(d.EndPath.Span))
                {
                    key = d.Value;
                    return true;
                }
            }
            return !key.IsEmpty;
        }
        internal static bool CheckPath(ReadOnlySpan<byte> path, out StringValue key, SiteConfig.PageConfig<StringValue>[] cfs)
        {
            key = StringValue.Empty;
            foreach (var d in cfs)
            {
                if (path.StartsWith(d.StartPath.Span) && path.EndsWith(d.EndPath.Span))
                {
                    key = d.Value;
                    return true;
                }
            }
            return false;
        }
        public string MD5(String src)
        {
            return MD5(src, this.Site.Site.Version);
        }
        public static string MD5(String src, String cap)
        {
            var md5 = System.Security.Cryptography.MD5.Create();
            byte[] md = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(src + cap));

            return UMC.Data.Utility.Parse36Encode(UMC.Data.Utility.IntParse(md));
        }
        public static string MD5(StringValue src)
        {
            var md5 = System.Security.Cryptography.MD5.Create();
            Span<byte> md = stackalloc byte[16];
            md5.TryComputeHash(src.Span, md, out var bytesWritten);

            return UMC.Data.Utility.Parse36Encode(UMC.Data.Utility.IntParse(md));
        }
        void OutputAppendJS(NetHttpResponse response, StringValue key, Stream output)
        {
            // var output = this.Compress(stream);
            var appender = new HttpAppender(response.Request, String.Format("SITE_JS_CONFIG_{0}{1}", this.Site.Root, MD5(key)).ToUpper());

            if (appender.IsStop || appender.AppendIndex == 0)
            {
                if (appender.IsStop == false)
                {
                    appender.Append(output.Write);
                    if (appender.IsStop)
                    {
                        output.Flush();
                        this.Context.OutputFinish();
                        return;
                    }

                }
                var buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(512);
                new HttpReadBody(r =>
                {
                    int len;
                    while ((len = r.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        output.Write(buffer, 0, len);
                    }

                }, e =>
                {
                    output.Flush();
                    System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
                    this.Context.OutputFinish();
                }, () => this.Context.Error(response.Error)).Append(response);

            }
            else
            {

                var bf = new byte[1];
                new HttpReadBody(r =>
                {
                    while (r.Read(bf, 0, 1) > 0)
                    {
                        if (appender.IsStop == false)
                        {
                            output.Write(bf, 0, 1);
                            if (bf[0] == '\n')
                            {
                                if (appender.Index == appender.AppendIndex)
                                {
                                    appender.Append(output.Write);
                                }
                                appender.Index++;
                            }
                        }
                    }

                }, e =>
                {

                    appender.Append(output.Write);
                    output.Flush();
                    output.Close();
                    this.Context.OutputFinish();
                }, () => this.Context.Error(response.Error)).Append(response);

            }

        }
        byte[] ReplaceHost(SiteConfig.ReplaceSetting replaceSetting, int start, StringValue rawUrl, int srcIndex, int destIndex)
        {
            var bytes = new List<byte>();

            var replacer = new HttpReplacer(this, (d, o, s) =>
            {
                int i = 0;
                while (i < s)
                {
                    bytes.Add(d[o + i]);
                    i++;
                }

            }, replaceSetting, srcIndex, destIndex);
            replacer.Replace((d, o, s) =>
            {
                if (start < rawUrl.Length)
                {
                    d[o] = rawUrl.Span[start];
                    start++;
                    return 1;
                }
                return 0;
            });
            replacer.Flush();

            return bytes.ToArray();
        }
        void CheckRawUrl()
        {

            if (this.Context.Query.IsEmpty == false)
            {
                this.CheckPath(this.Context.Path.Span, out var replaceSetting);

                this.Context.Memory.Temp(this.Context.Path.Span);
                this.Context.Memory.Temp(ReplaceHost(replaceSetting, 0, this.Context.Query, 0, 3));
                this.RawUrl = this.Context.Memory.Temp();

            }

        }

        StringValue ReplaceRedirect(StringValue redirect)
        {

            SiteConfig.ReplaceSetting rpsetting;

            CheckPath("Redirect"u8, out rpsetting);

            return new StringValue(ReplaceHost(rpsetting, 0, redirect, 1, 0));
        }

        StringValue OutputReplace(StringValue cookie, SiteConfig.ReplaceSetting rpsetting)
        {
            return new StringValue(ReplaceHost(rpsetting, 0, cookie, 1, 0));
        }
        void OuterReplaceHost(NetHttpResponse response, SiteConfig.ReplaceSetting rpsetting, Stream output, bool isEncoding, StringValue jsKey)
        {
            Stream stream;
            if (isEncoding)
            {
                stream = Compress(this.Context, output);
                // stream = Compress(output);

            }
            else
            {
                stream = output;
            }
            UMC.Net.TextWriter textWriter = new Net.TextWriter(stream.Write);
            if (jsKey.IsEmpty == false)
            {
                var appender = new HttpAppender(response.Request, String.Format("SITE_JS_CONFIG_{0}{1}", this.Site.Root, MD5(jsKey)).ToUpper());
                if (appender.IsStop || appender.AppendIndex == 0)
                {
                    appender.Append(textWriter.Write);
                    if (appender.IsStop)
                    {
                        textWriter.Flush();
                        textWriter.Close();
                        stream.Flush();
                        stream.Close();
                        this.Context.OutputFinish();
                        return;
                    }
                }
                else
                {
                    var replacer = new HttpReplacer(this, textWriter.Write, rpsetting, 1, 0);

                    new HttpReadBody(reader => replacer.Append(appender, reader.Read), e =>
                    {
                        replacer.Flush();
                        appender.Append(textWriter.Write);

                        textWriter.Flush();
                        textWriter.Close();

                        stream.Flush();
                        stream.Close();
                        this.Context.OutputFinish();
                    }, () =>
                    {
                        this.Context.Error(response.Error);

                        textWriter.Close();
                    }).Append(response);
                    return;

                }
            }
            {
                var replacer = new HttpReplacer(this, textWriter.Write, rpsetting, 1, 0);
                new HttpReadBody(reader => replacer.Replace(reader.Read), e =>
                {
                    replacer.Flush();

                    textWriter.Flush();
                    textWriter.Close();
                    stream.Flush();
                    stream.Close();

                    this.Context.OutputFinish();
                }, () =>
                {
                    textWriter.Close();
                    this.Context.Error(response.Error);
                }).Append(response);


            }
        }

        void OuterHTML(NetHttpResponse response, Stream output, bool isEncoding, StringValue jsKey)
        {

            Stream stream;
            if (isEncoding)
            {
                stream = Compress(this.Context, output);
            }
            else
            {
                stream = output;
            }
            var buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(0x400);
            int len, start = 0;
            bool isHead = true;
            new HttpReadBody(readData =>
            {
                while ((len = readData.Read(buffer, start, buffer.Length - start)) > 0)
                {
                    if (isHead)
                    {
                        int size = len + start;
                        int index = buffer.AsSpan(0, size).IndexOf(HttpReplacer.HtmlHeadEnd);
                        if (index == -1)
                        {
                            start = HttpReplacer.HtmlHeadEnd.Length;
                            if (size > start)
                            {
                                stream.Write(buffer, 0, size - start);
                                Array.Copy(buffer, size - start, buffer, 0, start);
                            }
                            else
                            {
                                start = size;
                            }
                        }
                        else
                        {
                            isHead = false;
                            stream.Write(buffer, 0, index);
                            var bData = UTF8Encoding.ASCII.GetBytes($"<script src=\"/UMC.Conf/{this.Site.Root}/{this.MD5(String.Empty)}/{HttpProxy.MD5(jsKey)}.js\"></script>\r\n");
                            stream.Write(bData, 0, bData.Length);
                            stream.Write(buffer, index, size - index);
                            start = 0;

                        }
                    }
                    else
                    {
                        stream.Write(buffer, start, len);
                    }

                }
            }, e =>
            {
                if (start > 0)
                {
                    stream.Write(buffer, 0, start);
                }
                stream.Flush();
                System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
                stream.Close();
                this.Context.OutputFinish();
            }, () =>
            {
                System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
                stream.Close();
                this.Context.Error(response.Error);
            }).Append(response);
        }
        static StringValue ContentEncodingBr = new StringValue("br"),
       ContentEncodingDeflate = new StringValue("deflate");
        public static Stream Compress(NetContext context, Stream output)
        {

            if (context.Headers.TryGet(StringValue.AcceptEncoding.Span, out var headValue))
            {
                var spanValue = headValue.Value.Span;

                if (spanValue.Contains(ContentEncodingBr.Span))
                {
                    context.AddHeader(StringValue.ContentEncoding, ContentEncodingBr);
                    return new BrotliStream(output, System.IO.Compression.CompressionMode.Compress);
                }
                else
                {

                    context.AddHeader(StringValue.ContentEncoding, ContentEncodingDeflate);
                    return new DeflateStream(output, CompressionMode.Compress);
                }
            }
            else
            {
                context.AddHeader(StringValue.ContentEncoding, ContentEncodingDeflate);
                return new DeflateStream(output, CompressionMode.Compress);
            }

        }
        void OuterHTML(NetHttpResponse response, SiteConfig.ReplaceSetting replaceSetting, Stream output, bool isEncoding, StringValue jsKey)
        {
            Stream stream;
            if (isEncoding)
            {
                stream = Compress(this.Context, output);
            }
            else
            {
                stream = output;
            }

            UMC.Net.TextWriter textWriter = new Net.TextWriter(stream.Write);

            var replacer = new HttpReplacer(this, textWriter.Write, replaceSetting, 1, 0);
            new HttpReadBody(jsKey.IsEmpty ? r => replacer.Replace(r.Read) : r => replacer.Html(jsKey, r.Read), e =>
            {
                replacer.Flush();
                textWriter.Flush();
                textWriter.Close();
                stream.Flush();
                stream.Close();
                this.Context.OutputFinish();
            }, () =>
            {
                textWriter.Close();
                stream.Close();
                this.Context.Error(response.Error);
            }).Append(response);

        }
        public static bool TryImageConf(StringValue confKey, out SiteConfig.ImageConfig confValue)
        {
            confValue = null;
            if (confKey.IsEmpty == false)
            {
                var image = new SiteConfig.ImageConfig() { Format = "Src" };
                var match = System.Text.RegularExpressions.Regex.Match(confKey.Span.UTF8(), "^[h|w|c|t|m|b](\\d+)([-|x]\\d+)?([g|p|j|w|a|o]?)$");
                confValue = image;
                if (match.Success)
                {
                    switch (match.Groups[3].Value)
                    {
                        case "g":
                            image.Format = "gif";
                            break;
                        case "j":
                            image.Format = "jpeg";
                            break;
                        case "w":
                            image.Format = "webp";
                            break;
                        case "p":
                            image.Format = "png";
                            break;
                        case "a":
                            image.Format = "avif";
                            break;
                        case "o":
                            image.Format = "Optimal";
                            break;

                    }
                    image.Width = Utility.IntParse(match.Groups[1].Value, 0);
                    if (match.Groups[2].Length > 0)
                    {
                        switch (match.Groups[0].Value[0])
                        {
                            case '-':
                                image.Width = -Utility.IntParse(match.Groups[1].Value, 0);
                                image.Height = -Utility.IntParse(match.Groups[0].Value, 0);
                                break;
                            default:
                                image.Height = Utility.IntParse(match.Groups[2].Value.Substring(1), 0);
                                break;
                        }
                    }
                    else
                    {

                        image.Height = Utility.IntParse(match.Groups[1].Value, 0);
                    }
                    switch (confKey.Span[0])
                    {
                        case (byte)'w':
                            image.Height = 0;
                            break;
                        case (byte)'h':
                            image.Width = 0;
                            break;
                        case (byte)'c':
                            image.Model = 0;
                            break;
                        case (byte)'t':
                            image.Model = 1;
                            break;
                        case (byte)'m':
                            image.Model = 2;
                            break;
                        case (byte)'b':
                            image.Model = 3;
                            break;
                    }
                    return true;
                }
                else if (confKey.Length == 1)
                {
                    switch (confKey.Span[0])
                    {
                        case (byte)'g':
                            image.Format = "gif";
                            return true;
                        case (byte)'j':
                            image.Format = "jpeg";
                            return true;
                        case (byte)'w':
                            image.Format = "webp";
                            return true;
                        case (byte)'p':
                            image.Format = "png";
                            return true;

                    }
                }
            }
            return false;

        }
        public static bool TryImageConfig(ReadOnlySpan<byte> path, SiteConfig site, out SiteConfig.ImageConfig confValue)
        {
            //      bool CheckPath(ReadOnlySpan<byte> path, StringValue ctype, out SiteConfig.ReplaceSetting replaceSetting)
            // {
            confValue = null;

            foreach (var v in site.ImagesConf)
            {
                if (path.StartsWith(v.StartPath.Span) && path.EndsWith(v.EndPath.Span))
                {
                    confValue = v.Value;
                    return true;
                }
            }

            return false;// confValue != null;

        }
        public static bool TryImageConfig(ReadOnlySpan<byte> path, ReadOnlySpan<byte> ctype, SiteConfig site, out SiteConfig.ImageConfig confValue)
        {
            //      bool CheckPath(ReadOnlySpan<byte> path, StringValue ctype, out SiteConfig.ReplaceSetting replaceSetting)
            // {
            confValue = null;

            foreach (var v in site.ImagesConf)
            {
                if (confValue == null)
                {
                    if (v.EndPath.IsEmpty && ctype.SequenceEqual(v.StartPath.Span))//, v.StartPath))
                    {
                        confValue = v.Value;
                        continue;
                    }
                }
                if (path.StartsWith(v.StartPath.Span) && path.EndsWith(v.EndPath.Span))
                {
                    confValue = v.Value;
                    return true;
                }
            }

            return confValue != null;

        }
    }
}
